Android加载Firestore数据时RecyclerView报No Adapter Attached错误如何解决
问题原因
- Firestore的
get()属于异步请求,不会阻塞主线程执行。Activity启动后系统会优先在主线程执行UI绘制流程,此时异步请求还未返回结果,RecyclerView没有绑定任何Adapter,就会触发No adapter attached; skipping layout报错。 - 你将Adapter的初始化和绑定逻辑全部放在异步请求的成功回调中,只要请求耗时较长、请求失败或者返回空数据,RecyclerView全程都无法获取到Adapter,必然会触发该报错。
修复方案
1. 修改onCreate逻辑,提前绑定空Adapter
在onCreate中完成RecyclerView初始化后直接创建空Adapter并绑定,不需要等待异步请求返回:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_journal_list); firebaseAuth= FirebaseAuth.getInstance(); user= firebaseAuth.getCurrentUser(); noJournalEntry= findViewById(R.id.list_no_thoughts); journalList= new ArrayList<>(); recyclerView= (RecyclerView) findViewById(R.id.recyclerView); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setHasFixedSize(true); // 新增:提前初始化空适配器并绑定到RecyclerView journalRecyclerAdapter= new JournalRecyclerAdapter(JournalListActivity.this, journalList); recyclerView.setAdapter(journalRecyclerAdapter); }
2. 修改onStart逻辑,仅更新数据源不重复创建Adapter
异步请求拿到数据后,直接更新已绑定的Adapter的数据源,再触发刷新即可,不需要重复创建Adapter:
@Override protected void onStart() { super.onStart(); // 获取当前登录用户的ID collectionReference.whereEqualTo("userId", JournalApi.getInstance() .getUserId()) .get() .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() { @Override public void onSuccess(QuerySnapshot queryDocumentSnapshots) { // 新增:清空原有数据,避免onStart多次触发导致数据重复 journalList.clear(); if(!queryDocumentSnapshots.isEmpty()) { noJournalEntry.setVisibility(View.GONE); for(QueryDocumentSnapshot journals: queryDocumentSnapshots){ Journal journal = journals.toObject(Journal.class); journalList.add(journal); Toast.makeText(JournalListActivity.this,"UserId found", Toast.LENGTH_LONG).show(); } // 直接通知适配器数据更新即可,不需要重新创建、绑定适配器 journalRecyclerAdapter.notifyDataSetChanged(); } else { noJournalEntry.setVisibility(View.VISIBLE); // 数据为空时也通知适配器刷新,清空列表展示 journalRecyclerAdapter.notifyDataSetChanged(); } } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // 请求失败时也清空列表,避免展示旧的错误数据 journalList.clear(); journalRecyclerAdapter.notifyDataSetChanged(); noJournalEntry.setVisibility(View.VISIBLE); Toast.makeText(JournalListActivity.this,"UserId NOT found", Toast.LENGTH_LONG).show(); } }); }
优化建议
- 后续如果有单条数据增删改的需求,优先使用
notifyItemInserted/notifyItemRemoved/notifyItemChanged等定向刷新方法,比全量刷新notifyDataSetChanged性能更高 - 如果需要实现下拉刷新、分页加载等功能,只需要修改
journalList的内容后调用对应刷新方法即可,不需要重复绑定Adapter
内容的提问来源于stack exchange,提问作者Sabyasachi Sahu
相关产品推荐
相关产品推荐

