Android Fragment中Firebase数据无法显示在RecyclerView的问题排查
Firebase实时数据库数据无法在Fragment的RecyclerView显示问题排查
我跟着视频教程在Fragment中实现了基于strings静态数据的RecyclerView,之后尝试结合另一个教程接入Firebase实时数据库获取数据,但数据始终无法正常显示。怀疑是生命周期方法中的函数调用有误,以下是我的相关代码,请帮忙排查问题所在:
HomeFragment.java(Fragment类)
package com.example.foodapp.deliverer; import android.os.Bundle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.example.foodapp.R; import com.google.firebase.database.DataSnapshot; import com.google.firebase.database.DatabaseError; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; import com.google.firebase.database.ValueEventListener; import java.util.ArrayList; public class HomeFragment extends Fragment { private ArrayList<OrderItem> orderItemArrayList; RecyclerView recyclerview; DatabaseReference DB; ItemRecyclerAdapter itemRecyclerAdapter; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.delivery_fragment_home, container, false); return view; } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); recyclerview = view.findViewById(R.id.delivery_orders_recyclerView); DB = FirebaseDatabase.getInstance().getReference("Delivery"); recyclerview.setHasFixedSize(true); recyclerview.setLayoutManager(new LinearLayoutManager(getContext())); orderItemArrayList = new ArrayList<>(); itemRecyclerAdapter = new ItemRecyclerAdapter(getContext(), orderItemArrayList); recyclerview.setAdapter(itemRecyclerAdapter); DB.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { for(DataSnapshot dataSnapshot: snapshot.getChildren()){ OrderItem item = dataSnapshot.child("Delivery").getValue(OrderItem.class); orderItemArrayList.add(item); } } @Override public void onCancelled(@NonNull DatabaseError error) { } }); itemRecyclerAdapter.notifyDataSetChanged(); } }
delivery_fragment_home.xml(Fragment布局)
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/linearLayout" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".deliverer.HomeFragment" > <androidx.recyclerview.widget.RecyclerView android:id="@+id/delivery_orders_recyclerView" android:layout_width="409dp" android:layout_height="729dp" android:background="#CDDC39" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" tools:listitem="@layout/delivery_orderitem" /> </androidx.constraintlayout.widget.ConstraintLayout>
OrderItem.java(RecyclerView数据类)
package com.example.foodapp.deliverer; public class OrderItem { private String orderID; private String Address; public OrderItem(String orderID, String Address) { this.orderID = orderID; this.Address = Address; } public String getOrderID() { return orderID; } public String getAddress() { return Address; } }
delivery_orderItem.xml(RecyclerView子项布局)
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="15dp" android:layout_marginTop="15dp" android:text="@string/lbl_orderId" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/textView3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="15dp" android:layout_marginTop="8dp" android:layout_marginBottom="15dp" android:text="@string/lbl_address" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView2" /> <TextView android:id="@+id/lbl_orderId" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="12dp" android:layout_marginTop="15dp" android:text="TextView" app:layout_constraintStart_toEndOf="@+id/textView2" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/lbl_address" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:layout_marginBottom="15dp" android:text="TextView" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="@+id/lbl_orderId" app:layout_constraintTop_toBottomOf="@+id/lbl_orderId" /> </androidx.constraintlayout.widget.ConstraintLayout>
ItemRecyclerAdapter.java(适配器类)
package com.example.foodapp.deliverer; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import com.example.foodapp.R; import java.util.ArrayList; public class ItemRecyclerAdapter extends RecyclerView.Adapter<ItemRecyclerAdapter.DriverItemViewHolder> { Context context; ArrayList<OrderItem> itemArrayList; public ItemRecyclerAdapter(Context context, ArrayList<OrderItem> itemList) { this.context = context; this.itemArrayList = itemList; } @NonNull @Override public DriverItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View v = LayoutInflater.from(context).inflate(R.layout.delivery_orderitem, parent, false); return new DriverItemViewHolder(v); } @Override public void onBindViewHolder(@NonNull ItemRecyclerAdapter.DriverItemViewHolder holder, int position) { OrderItem order = itemArrayList.get(position); holder.orderID.setText(order.getOrderID()); holder.address.setText(order.getAddress()); } @Override public int getItemCount() { return itemArrayList .size(); } public static class DriverItemViewHolder extends RecyclerView.ViewHolder{ private TextView orderID; private TextView address; public DriverItemViewHolder(@NonNull View itemView) { super(itemView); this.orderID = itemView.findViewById(R.id.lbl_orderId); this.address = itemView.findViewById(R.id.lbl_address); } } }
问题排查及修复方案
1. Firebase数据读取路径错误
你已经将DB指向了"Delivery"节点,遍历snapshot.getChildren()得到的是Delivery下的所有子节点,此时不需要再调用dataSnapshot.child("Delivery"),否则会在子节点下再次查找Delivery节点,导致读取不到数据。
修复后代码:
@Override public void onDataChange(@NonNull DataSnapshot snapshot) { orderItemArrayList.clear(); // 先清空旧数据,避免重复加载 for(DataSnapshot dataSnapshot: snapshot.getChildren()){ OrderItem item = dataSnapshot.getValue(OrderItem.class); if(item != null){ // 判空避免空指针 orderItemArrayList.add(item); } } itemRecyclerAdapter.notifyDataSetChanged(); // 数据更新后通知适配器 }
2. 适配器通知更新时机错误
Firebase数据读取是异步操作,notifyDataSetChanged()放在addValueEventListener外面会先于数据返回执行,此时列表还是空的,通知更新无效。必须将通知放在onDataChange方法内部,确保数据加载完成后再更新UI。
3. OrderItem类缺少无参构造函数
Firebase的反序列化需要类提供无参构造函数,否则无法将数据库中的数据映射为Java对象,导致获取到的OrderItem实例为null。
修复后OrderItem类:
package com.example.foodapp.deliverer; public class OrderItem { private String orderID; private String address; // 统一为小写,和数据库字段匹配 // 必须添加无参构造函数 public OrderItem() {} public OrderItem(String orderID, String address) { this.orderID = orderID; this.address = address; } public String getOrderID() { return orderID; } public String getAddress() { return address; } }
4. 变量名大小写不匹配
原代码中OrderItem的Address字段是大写开头,若Firebase数据库中的字段是小写的address,会导致映射失败。统一变量名为小写,或者使用@PropertyName注解指定数据库字段名。
完成以上修改后,Firebase的数据应该能正常加载到RecyclerView中了。
内容的提问来源于stack exchange,提问作者Priyantha Fernando
相关产品推荐
相关产品推荐

