Firestore数据可在Toast显示但RecyclerView不加载,FirebaseUI无效
问题:Firestore数据在RecyclerView不显示但Toast可正常展示
尝试从Firestore读取数据并在RecyclerView中展示,但数据未显示且无报错;不过将数据传入Toast时能正常显示。已尝试使用FirebaseUI,但同样无法解决问题。
依赖配置
dependencies { implementation 'com.firebaseui:firebase-ui-auth:8.0.1' implementation 'com.firebaseui:firebase-ui-database:8.0.1' implementation 'androidx.fragment:fragment-ktx:1.5.5' implementation 'androidx.appcompat:appcompat:1.5.1' implementation 'com.google.android.material:material:1.7.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'com.google.firebase:firebase-storage:20.0.1' implementation 'com.google.firebase:firebase-database:20.0.4' implementation 'androidx.gridlayout:gridlayout:1.0.0' implementation 'com.google.firebase:firebase-firestore-ktx:24.4.4' testImplementation 'junit:junit:4.13.2' implementation 'com.karumi:dexter:6.2.3' implementation 'com.firebaseui:firebase-ui-firestore:8.0.1' androidTestImplementation 'androidx.test.ext:junit:1.1.4' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0' }
主Fragment代码
public class createdplaylist extends Fragment { ArrayList<String> str=new ArrayList<>(); RecyclerView recyclerView; palylistadapter palylistadapter; Context context; FirestoreRecyclerAdapter adapter; FirebaseFirestore firestore; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_createdplaylist, container, false); context=container.getContext(); firestore = FirebaseFirestore.getInstance(); Query query=firestore.collection("playlist"); recyclerView =view.findViewById(R.id.recyclerr); query.addSnapshotListener(new EventListener<QuerySnapshot>() { @Override public void onEvent(@Nullable QuerySnapshot value, @Nullable FirebaseFirestoreException error) { for(DocumentSnapshot ds: value.getDocuments()){ str.add(ds.getId()); Toast.makeText(context, ds.getId(), Toast.LENGTH_SHORT).show(); } } }); palylistadapter=new palylistadapter(context,str); recyclerView.setLayoutManager(new LinearLayoutManager(context)); recyclerView.setHasFixedSize(true); recyclerView.setAdapter(palylistadapter); return view; }
Adapter代码
public class palylistadapter extends RecyclerView.Adapter<palylistadapter.viewhold> { Context context; ArrayList<String>list; public palylistadapter( Context c,ArrayList<String>s){ this.list=s; this.context=c; } @NonNull @Override public viewhold onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View v= LayoutInflater.from(context).inflate(R.layout.playlistlayout,parent,false); viewhold viewhold=new viewhold(v); return viewhold; } @Override public void onBindViewHolder(@NonNull viewhold holder, int position) { holder.t.setText(list.get(position)); } @Override public int getItemCount() { if(list.isEmpty()) return 0; else return list.size(); } public class viewhold extends RecyclerView.ViewHolder { TextView t; public viewhold(@NonNull View itemView) { super(itemView); t=itemView.findViewById(R.id.textname); } }
问题原因与解决方案
核心原因
Firestore的addSnapshotListener是异步操作,当你初始化palylistadapter并绑定到RecyclerView时,Firestore的数据还未返回,此时str列表为空。后续数据返回并添加到列表后,没有通知Adapter数据已更新,导致RecyclerView不会刷新界面。
解决方案1:手动通知Adapter更新数据
修改Fragment中的快照监听回调,在数据添加完成后调用Adapter的notifyDataSetChanged()方法,触发界面刷新:
query.addSnapshotListener(new EventListener<QuerySnapshot>() { @Override public void onEvent(@Nullable QuerySnapshot value, @Nullable FirebaseFirestoreException error) { if (error != null) { // 处理异常,避免崩溃 return; } // 清空旧数据,防止重复添加 str.clear(); for(DocumentSnapshot ds: value.getDocuments()){ str.add(ds.getId()); Toast.makeText(context, ds.getId(), Toast.LENGTH_SHORT).show(); } // 通知Adapter数据已更新 palylistadapter.notifyDataSetChanged(); } });
注意:确保palylistadapter在回调前已完成初始化,避免空指针异常。
解决方案2:使用FirebaseUI的FirestoreRecyclerAdapter(推荐)
利用FirebaseUI封装好的适配器,自动处理数据监听、更新和生命周期管理,无需手动维护列表:
步骤1:创建数据模型类
public class Playlist { private String id; public Playlist() {} public Playlist(String id) { this.id = id; } public String getId() { return id; } }
步骤2:修改Fragment代码
public class createdplaylist extends Fragment { RecyclerView recyclerView; FirebaseFirestore firestore; FirestoreRecyclerAdapter<Playlist, PlaylistViewHolder> adapter; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_createdplaylist, container, false); Context context = container.getContext(); firestore = FirebaseFirestore.getInstance(); recyclerView = view.findViewById(R.id.recyclerr); recyclerView.setLayoutManager(new LinearLayoutManager(context)); recyclerView.setHasFixedSize(true); // 构建Firestore查询 Query query = firestore.collection("playlist"); // 配置FirestoreRecyclerOptions FirestoreRecyclerOptions<Playlist> options = new FirestoreRecyclerOptions.Builder<Playlist>() .setQuery(query, snapshot -> new Playlist(snapshot.getId())) .build(); // 初始化适配器 adapter = new FirestoreRecyclerAdapter<Playlist, PlaylistViewHolder>(options) { @NonNull @Override public PlaylistViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.playlistlayout, parent, false); return new PlaylistViewHolder(v); } @Override protected void onBindViewHolder(@NonNull PlaylistViewHolder holder, int position, @NonNull Playlist model) { holder.t.setText(model.getId()); Toast.makeText(context, model.getId(), Toast.LENGTH_SHORT).show(); } }; recyclerView.setAdapter(adapter); return view; } // 开始监听数据 @Override public void onStart() { super.onStart(); if (adapter != null) { adapter.startListening(); } } // 停止监听,避免内存泄漏 @Override public void onStop() { super.onStop(); if (adapter != null) { adapter.stopListening(); } } // 自定义ViewHolder public static class PlaylistViewHolder extends RecyclerView.ViewHolder { TextView t; public PlaylistViewHolder(@NonNull View itemView) { super(itemView); t = itemView.findViewById(R.id.textname); } } }
这种方式会自动处理数据的新增、修改和删除,同时在Fragment生命周期内管理监听的启停,避免不必要的资源消耗。
内容的提问来源于stack exchange,提问作者mm m
相关产品推荐
相关产品推荐

