java - एंड्रॉइड के साथ फायरस्टार को कैसे शांत करना है?




android firebase (2)

मैंने फायरस्टार प्रलेखन और इंटरनेट पर सभी लेख (स्टायरोवरफ़्लो) फायरस्टार पेजिनेशन के बारे में पढ़ा लेकिन कोई भाग्य नहीं। मैंने डॉक्स में सटीक कोड लागू करने की कोशिश की, लेकिन ऐसा कुछ नहीं हुआ। मेरे पास आइटम (1250 या अधिक से अधिक) के साथ एक बुनियादी डेटाबेस है और मैं उन्हें उत्तरोत्तर प्राप्त करना चाहता हूं। 15 आइटम लोड करने के लिए स्क्रॉल करके (डेटाबेस में अंतिम आइटम के लिए)।

यदि डॉक्स कोड का उपयोग कर रहे हैं:

// Construct query for first 25 cities, ordered by population
Query first = db.collection("cities")
    .orderBy("population")
    .limit(25);

first.get()
    .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
    @Override
    public void onSuccess(QuerySnapshot documentSnapshots) {
        // ...

        // Get the last visible document
        DocumentSnapshot lastVisible = documentSnapshots.getDocuments()
            .get(documentSnapshots.size() -1);

        // Construct a new query starting at this document,
        // get the next 25 cities.
        Query next = db.collection("cities")
            .orderBy("population")
            .startAfter(lastVisible)
            .limit(25);

        // Use the query for pagination
        // ...
    }
});

कैसे करें? दस्तावेज़ीकरण में बहुत अधिक विवरण नहीं हैं।

पुनश्च: जब उपयोगकर्ता स्क्रॉल करता है तो मुझे पुनर्नवीनीकरण दृश्य (सूची दृश्य नहीं) की आवश्यकता होती है। धन्यवाद


FirebaseUI-Android भी हाल ही में फायरस्टार पेजिनेटर के साथ सामने आया है।

मैंने इसे अपने कोड में उपयोग किया है, और यह बहुत अच्छा काम करता है - बस ध्यान रखें कि यह .addSnapshotListener () के बजाय .get () का उपयोग करता है, इसलिए पुनर्नवीनीकरण वास्तविक समय में नहीं है।

यहां डॉक्स देखें:

https://github.com/firebase/FirebaseUI-Android/tree/master/firestore#using-the-firestorepagingadapter


जैसा कि यह आधिकारिक दस्तावेज में उल्लेख किया गया है, इस समस्या को हल करने के लिए महत्वपूर्ण है startAfter() विधि का उपयोग करना। तो आप क्वेरी कर्सर को limit() विधि के साथ जोड़कर प्रश्नों को शांत कर सकते हैं। आप अगले बैच के लिए कर्सर की शुरुआत के रूप में एक बैच में अंतिम दस्तावेज़ का उपयोग करने में सक्षम होंगे।

इस पेजिनेशन की समस्या को हल करने के लिए, कृपया इस post से मेरा उत्तर देखें, जिसमें मैंने स्टेप बाई स्टेप बताया है कि कैसे आप क्लाउड फायरस्टार डेटाबेस से डेटा को छोटे-छोटे हिस्सों में लोड कर सकते हैं और इसे बटन क्लिक पर ListView में प्रदर्शित कर सकते हैं।

उपाय:

अपने Firestore डेटाबेस से डेटा प्राप्त करने के लिए और इसे RecyclerView में छोटे विखंडू में प्रदर्शित करें, कृपया नीचे दिए गए चरणों का पालन करें।

आइए उपरोक्त उदाहरण लेते हैं जिसमें मैंने उत्पादों का उपयोग किया है। आप उत्पादों, शहरों या आप जो चाहें उपयोग कर सकते हैं। सिद्धांत समान हैं। यह मानकर कि आप उपयोगकर्ता स्क्रॉल करते समय अधिक उत्पाद लोड करना चाहते हैं, मैं RecyclerView.OnScrollListener उपयोग करूंगा।

आइए पहले RecyclerView को परिभाषित करें, लेआउट प्रबंधक को LinearLayoutManager सेट करें और एक सूची बनाएं। हम खाली सूची का उपयोग करके भी एडाप्टर को तुरंत हटा देते हैं और एडेप्टर को हमारे RecyclerView सेट करते हैं:

RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
List<ProductModel> list = new ArrayList<>();
ProductAdapter productAdapter = new ProductAdapter(list);
recyclerView.setAdapter(productAdapter);

मान लें कि हमारे पास एक डेटाबेस संरचना है जो इस तरह दिखती है:

Firestore-root
   |
   --- products (collection)
         |
         --- productId (document)
                |
                --- productName: "Product Name"

और एक मॉडल वर्ग जो इस तरह दिखता है:

public class ProductModel {
    private String productName;

    public ProductModel() {}

    public ProductModel(String productName) {this.productName = productName;}

    public String getProductName() {return productName;}
}

यह कैसे एडाप्टर वर्ग की तरह दिखना चाहिए:

private class ProductAdapter extends RecyclerView.Adapter<ProductViewHolder> {
    private List<ProductModel> list;

    ProductAdapter(List<ProductModel> list) {
        this.list = list;
    }

    @NonNull
    @Override
    public ProductViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_product, parent, false);
        return new ProductViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ProductViewHolder productViewHolder, int position) {
        String productName = list.get(position).getProductName();
        productViewHolder.setProductName(productName);
    }

    @Override
    public int getItemCount() {
        return list.size();
    }
}

item_product लेआउट में केवल एक दृश्य, एक item_product शामिल है।

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/text_view"
    android:textSize="25sp"/>

और यह है कि धारक वर्ग को कैसा दिखना चाहिए:

private class ProductViewHolder extends RecyclerView.ViewHolder {
    private View view;

    ProductViewHolder(View itemView) {
        super(itemView);
        view = itemView;
    }

    void setProductName(String productName) {
        TextView textView = view.findViewById(R.id.text_view);
        textView.setText(productName);
    }
}

अब, एक सीमा को वैश्विक चर के रूप में परिभाषित करते हैं और इसे 15 सेट करते हैं।

private int limit = 15;

आइए अब इस सीमा का उपयोग करके क्वेरी को परिभाषित करें:

FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference productsRef = rootRef.collection("products");
Query query = productsRef.orderBy("productName", Query.Direction.ASCENDING).limit(limit);

यहाँ वह कोड है जो आपके मामले में भी जादू करता है:

query.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
    @Override
    public void onComplete(@NonNull Task<QuerySnapshot> task) {
        if (task.isSuccessful()) {
            for (DocumentSnapshot document : task.getResult()) {
                ProductModel productModel = document.toObject(ProductModel.class);
                list.add(productModel);
            }
            productAdapter.notifyDataSetChanged();
            lastVisible = task.getResult().getDocuments().get(task.getResult().size() - 1);

            RecyclerView.OnScrollListener onScrollListener = new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
                    if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
                        isScrolling = true;
                    }
                }

                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);

                    LinearLayoutManager linearLayoutManager = ((LinearLayoutManager) recyclerView.getLayoutManager());
                    int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
                    int visibleItemCount = linearLayoutManager.getChildCount();
                    int totalItemCount = linearLayoutManager.getItemCount();

                    if (isScrolling && (firstVisibleItemPosition + visibleItemCount == totalItemCount) && !isLastItemReached) {
                        isScrolling = false;
                        Query nextQuery = productsRef.orderBy("productName", Query.Direction.ASCENDING).startAfter(lastVisible).limit(limit);
                        nextQuery.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                            @Override
                            public void onComplete(@NonNull Task<QuerySnapshot> t) {
                                if (t.isSuccessful()) {
                                    for (DocumentSnapshot d : t.getResult()) {
                                        ProductModel productModel = d.toObject(ProductModel.class);
                                        list.add(productModel);
                                    }
                                    productAdapter.notifyDataSetChanged();
                                    lastVisible = t.getResult().getDocuments().get(t.getResult().size() - 1);

                                    if (t.getResult().size() < limit) {
                                        isLastItemReached = true;
                                    }
                                }
                            }
                        });
                    }
                }
            };
            recyclerView.addOnScrollListener(onScrollListener);
        }
    }
});

जिसमें lastVisible एक DocumentSnapshot ऑब्जेक्ट है जो क्वेरी से अंतिम विज़िबाइल आइटम का प्रतिनिधित्व करता है। इस स्थिति में, प्रत्येक 15'th एक और इसे ग्लोबबल वेरिएबल घोषित किया जाता है:

private DocumentSnapshot lastVisible;

और isScrolling और isLastItemReached भी वैश्विक चर हैं और इन्हें निम्न रूप में घोषित किया गया है:

private boolean isScrolling = false;
private boolean isLastItemReached = false;

यदि आप वास्तविक समय में डेटा प्राप्त करना चाहते हैं, तो एक संग्रह में कई दस्तावेज़ों को सुनने के संबंध में आधिकारिक दस्तावेज में बताए अनुसार आपको addSnapshotListener() का उपयोग करने की आवश्यकता है।





google-cloud-firestore