卡片在从Firestore获取数据后未更新。

huangapple go评论72阅读模式
英文:

Cards not updating after fetching data in Firestore

问题

我正在尝试编写一个库存管理系统的应用程序,我唯一需要做的事情是能够显示一个可以点击的类别列表,然后将您带到该类别中的产品列表。我正在使用带有RecyclerView的CardView,它们都在一个片段上操作(因为我正在使用导航抽屉)。如果我传入一个预定义的ArrayList,我可以成功显示卡片,但是当我从Firestore中获取数据时,卡片中就不会显示任何内容,尽管我仍然使用相同的ArrayList,但数据只是来自不同的来源。我仍然是Android的初学者,如果有人能帮助我,我将不胜感激。以下是我的Fragment类的代码。

package com.example.drawerplayground;

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.QueryDocumentSnapshot;
import com.google.firebase.firestore.QuerySnapshot;

import java.util.ArrayList;
import java.util.HashMap;

public class InventoryFragment extends Fragment {

    private TextView tv;
    private HashMap<String, Object> categories;
    private ArrayList<String> cats;
    private FirebaseFirestore db;
    private InventoryAdapter adapter;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        cats = new ArrayList<>();
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View inventoryView = inflater.inflate(R.layout.fragment_inventory, container, false);
        RecyclerView recyclerView = (RecyclerView) inventoryView.findViewById(R.id.recycler_view);
        adapter = new InventoryAdapter(getContext(), cats);
        GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(), 2);
        recyclerView.setLayoutManager(gridLayoutManager);
        recyclerView.setAdapter(adapter);
        getCategories();
        return inventoryView;
    }

    public void getCategories() {
        cats = new ArrayList<>();
        db = FirebaseFirestore.getInstance();
        db.collection("categories")
                .get()
                .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                    @Override
                    public void onComplete(@NonNull Task<QuerySnapshot> task) {
                        if (task.isSuccessful()) {
                            for (QueryDocumentSnapshot document : task.getResult()) {
                                cats.add(document.get("categoryName").toString());
                                Log.d("fragment", document.get("categoryName").toString());
                            }
                            adapter.notifyDataSetChanged(); // Move this line here
                        }
                    }
                });
    }
}

我尝试在适配器上使用 notifyDataSetChanged() 方法,并尝试将数据获取操作放在单独的函数中,如上所示。

请注意,在成功获取数据后,我将 adapter.notifyDataSetChanged(); 移动到了正确的位置,以确保在数据准备好后通知适配器更新数据。

数据库结构如下,您有一个类别的集合,每个文档表示不同的类别,每个文档包含一个id和一个categoryName字段。这是一个非常基本和小型的结构,只是为了在开始实际项目之前测试潜在功能。

如果您有任何其他问题或需要进一步的帮助,请随时提问。

英文:

I am trying to write an app for an inventory management system and the one thing I need to do is to be able to display a list of categories that can be clicked on that will then take you to a list of products in that category. I am using a CardView with a RecyclerView, that both act on a fragment (as I am using a navigation drawer). I was able to get the cards to show successfully if a passed in a pre-defined ArrayList, but when I now fetch the data from Firestore, none of the cards want to appear, yet I am still using the same ArrayList, but the data is just coming from a different source. I am still a beginner in Android and would really appreciate it if someone could please help me. Here is my code for the Fragment class.

package com.example.drawerplayground;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.QueryDocumentSnapshot;
import com.google.firebase.firestore.QuerySnapshot;
import java.util.ArrayList;
import java.util.HashMap;
public class InventoryFragment extends Fragment {
private TextView tv;
private HashMap&lt;String, Object&gt; categories;
private ArrayList&lt;String&gt; cats;
private FirebaseFirestore db;
private InventoryAdapter adapter;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
cats = new ArrayList&lt;&gt;();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View inventoryView = inflater.inflate(R.layout.fragment_inventory, container, false);
RecyclerView recyclerView = (RecyclerView) inventoryView.findViewById(R.id.recycler_view);
adapter = new InventoryAdapter(getContext(), cats);
GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(), 2);
recyclerView.setLayoutManager(gridLayoutManager);
recyclerView.setAdapter(adapter);
getCategories();
return inventoryView;
}
public void getCategories()
{
cats = new ArrayList&lt;&gt;();
db = FirebaseFirestore.getInstance();
db.collection(&quot;categories&quot;)
.get()
.addOnCompleteListener(new OnCompleteListener&lt;QuerySnapshot&gt;() {
@Override
public void onComplete(@NonNull Task&lt;QuerySnapshot&gt; task) {
if(task.isSuccessful())
{
for(QueryDocumentSnapshot document : task.getResult())
{
cats.add(document.get(&quot;categoryName&quot;).toString());
Log.d(&quot;fragment&quot;, document.get(&quot;categoryName&quot;).toString());
}
}
}
});
adapter.notifyDataSetChanged();
}
}

I tried using the notifyDataSetChanged() method for the adapter and also tried to perform the fetching of data in a separate function, as you can see above.

---EDIT---
Below you can see my basic idea of what the database structure looks like, I have a collection of categories, with each document being a different category and each document will contain an id and a categoryName field. It is a very basic and small structure for now, as my aim was to play around with the potential functionality before I started with the project itself.
卡片在从Firestore获取数据后未更新。

答案1

得分: 2

I notice you are calling adapter.notifyDataSetChanged() but I was not able to find where you are actually giving updated list of cats to your adapter.

You should adjust your adapter and do following changes-

Add setCatList() method

public void setCatList(List<String> catList) {
    this.catList= catList;
    notifyDataSetChanged();
}

Modify your getItemCount() method

@Override
public int getItemCount() {
    if (catList!= null)
        return catList.size();
    else
        return 0;
}

So structure of your InventoryAdapter will be as follow-

public class InventoryAdapter extends RecyclerView.Adapter<InventoryAdapter.CustomViewHolder> {
    
    private Context context;
    private List<String> catList;

    public InventoryAdapter(Context context) {
        this.context = context;
    }
    
    public CustomViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new CustomViewHolder(LayoutInflater.from(context).inflate(R.layout.cat_item_layout, parent, false));
    }

    @Override
    public void onBindViewHolder(@NonNull CustomViewHolder holder, int position) {
    // setup binding of views
    }

    public void setCatList(List<String> catList) {
        this.catList= catList;
        notifyDataSetChanged();
    }

    @Override
    public int getItemCount() {
        if (catList!= null)
            return catList.size();
        else
            return 0;
    }

    //inner class of CustomViewHolder
}

Then you there is no need to create new ArrayList<>() under onCreate() and onCreateView(). This is how you will create your adapter -

adapter = new InventoryAdapter(getContext());

and getCategories() will be as follows -

public void getCategories()
{
    db = FirebaseFirestore.getInstance();
    db.collection("categories")
            .get()
            .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                    if(task.isSuccessful())
                    {
                        List<String> cats = new ArrayList();
                        for(QueryDocumentSnapshot document : task.getResult()){
                            cats.add(document.get("categoryName").toString());
                            Log.d("fragment", document.get("categoryName").toString());
                        }
                        adapter.setCatList(cats ); //simply give updated cats list to recycle adapter
                    }
                }
            });
}

No need to call adapter.notifyDataSetChanged() because that will be taken care under setCatList() method of adapter.

If you want to preserve the catList then you can modify setCatList() accordingly as put a if check, if there is some data already or not as follows -

public void setCatList(List<String> catList) {
    if(this.catList!=null){
        if(this.catList.size()!=0){
            //there is some cat item inside already, take action accordingly 
        }
        else
            this.catList= catList;
    }
    else{
        this.catList= catList;
    }

    notifyDataSetChanged();
}

Happy Coding !

英文:

I notice you are calling adapter.notifyDataSetChanged() but I was not able to find where you are actually giving updated list of cats to your adapter.

You should adjust your adapter and do following changes-

Add setCatList() method

public void setCatList(List&lt;String&gt; catList) {
this.catList= catList;
notifyDataSetChanged();
}

Modify your getItemCount() method

@Override
public int getItemCount() {
if (catList!= null)
return catList.size();
else
return 0;
}

So structure of your InventoryAdapter will be as follow-

public class InventoryAdapter extends RecyclerView.Adapter&lt;InventoryAdapter.CustomViewHolder&gt; {
private Context context;
private List&lt;String&gt; catList;
public InventoryAdapter(Context context) {
this.context = context;
}
public CustomViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new CustomViewHolder(LayoutInflater.from(context).inflate(R.layout.cat_item_layout, parent, false));
}
@Override
public void onBindViewHolder(@NonNull CustomViewHolder holder, int position) {
// setup binding of views
}
public void setCatList(List&lt;String&gt; catList) {
this.catList= catList;
notifyDataSetChanged();
}
@Override
public int getItemCount() {
if (catList!= null)
return catList.size();
else
return 0;
}
//inner class of CustomViewHolder
}

Then you there is no need to create new ArrayList&lt;&gt;() under onCreate() and onCreateView(). This is how you will create your adapter -

adapter = new InventoryAdapter(getContext());

and getCategories() will be as follows -

public void getCategories()
{
db = FirebaseFirestore.getInstance();
db.collection(&quot;categories&quot;)
.get()
.addOnCompleteListener(new OnCompleteListener&lt;QuerySnapshot&gt;() {
@Override
public void onComplete(@NonNull Task&lt;QuerySnapshot&gt; task) {
if(task.isSuccessful())
{
List&lt;String&gt; cats = new ArrayList();
for(QueryDocumentSnapshot document : task.getResult()){
cats.add(document.get(&quot;categoryName&quot;).toString());
Log.d(&quot;fragment&quot;, document.get(&quot;categoryName&quot;).toString());
}
adapter.setCatList(cats ); //simply give updated cats list to recycle adapter
}
}
});
}

No need to call adapter.notifyDataSetChanged() because that will be taken care under setCatList() method of adapter.

If you want to preserve the catList then you can modify setCatList() accordingly as put a if check, if there is some data already or not as follows -

public void setCatList(List&lt;String&gt; catList) {
if(this.catList!=null){
if(this.catList.size()!=0){
//there is some cat item inside already, take action accordingly 
}
else
this.catList= catList;
}
else{
this.catList= catList;
}
notifyDataSetChanged();
}

Happy Coding !

huangapple
  • 本文由 发表于 2020年8月7日 18:20:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/63299829.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定