Android应用无法从Firebase Realtime Database获取数据求助
问题:Android应用无法从Firebase Realtime Database获取数据,RecyclerView显示为空
我开发的Java Android应用无法从Firebase Realtime Database中获取数据,RecyclerView显示为空。Logcat显示获取到的数据条数为0,应用运行无报错。尝试过使用模型类和手动读取两种方式均无效,已开放数据库读写权限。
相关代码
Home.java
package com.example.rsvpea; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.ImageButton; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.example.rsvpea.Models.UploadEventModel; 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 Home extends AppCompatActivity { public static ImageButton home; public static ImageButton bookings; public static ImageButton profile; FirebaseDatabase database; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); home = findViewById(R.id.home); bookings = findViewById(R.id.myBookings); profile = findViewById(R.id.myProfile); BottomNavBar buttonClickListenerHome = new BottomNavBar(home); BottomNavBar buttonClickListenerBookings = new BottomNavBar(bookings); BottomNavBar buttonClickListenerProfile = new BottomNavBar(profile); ArrayList<TimelineCardContent> timelineCardContents = new ArrayList<>(); RecyclerView timeline = findViewById(R.id.timelineRecyclerView); timeline.setLayoutManager(new LinearLayoutManager(this)); database=FirebaseDatabase.getInstance(); database.getReference().child("Event List").addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { for(DataSnapshot itemSnapshot : snapshot.getChildren()){ //String img = itemSnapshot.child("image").getValue(String.class); //String eventTitle = itemSnapshot.child("eventTitle").getValue(String.class); UploadEventModel temp = itemSnapshot.getValue(UploadEventModel.class); timelineCardContents.add(new TimelineCardContent(temp.getImage(), temp.getEventTitle())); } Log.d("FirebaseData", "Data retrieved: " + timelineCardContents.size() + " items"); } @Override public void onCancelled(@NonNull DatabaseError error) { Toast.makeText(Home.this, "Error", Toast.LENGTH_SHORT).show(); } }); RecycleContentAdapter adapter = new RecycleContentAdapter(this, timelineCardContents); System.out.println(timelineCardContents); timeline.setAdapter(adapter); home.setOnClickListener(buttonClickListenerHome); profile.setOnClickListener(buttonClickListenerProfile); bookings.setOnClickListener(buttonClickListenerBookings); findViewById(R.id.uploadnewevent).setOnClickListener(view -> { Intent intent = new Intent(Home.this, UploadActivity.class); Home.this.startActivity(intent); }); } }
Adapter类
package com.example.rsvpea; import android.content.Context; import android.content.Intent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import com.squareup.picasso.Picasso; import java.util.ArrayList; public class RecycleContentAdapter extends RecyclerView.Adapter<RecycleContentAdapter.ViewHolder> { Context context; ArrayList<TimelineCardContent> arrContent; RecycleContentAdapter(Context context, ArrayList<TimelineCardContent> arrContent){ this.context=context; this.arrContent=arrContent; } @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View v= LayoutInflater.from(context).inflate(R.layout.timeline_item, parent, false); return new ViewHolder(v); } @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { TimelineCardContent content = arrContent.get(position); //holder.img.setImageResource(arrContent.get(position).img); Picasso.get() .load(content.img) .into(holder.img); holder.title.setText(arrContent.get(position).title); holder.moreDetailsButton.setOnClickListener(v -> { Intent intent = new Intent(v.getContext(), MoreDetails.class); v.getContext().startActivity(intent); }); } @Override public int getItemCount() { return arrContent.size(); } public class ViewHolder extends RecyclerView.ViewHolder{ TextView title; ImageView img; Button moreDetailsButton; public ViewHolder(@NonNull View itemView) { super(itemView); this.title=itemView.findViewById(R.id.title); this.img=itemView.findViewById(R.id.img); moreDetailsButton = itemView.findViewById(R.id.moreDetails); } } }
事件模型类
package com.example.rsvpea.Models; public class UploadEventModel { private String eventTitle, Desc, date, venue, image; public UploadEventModel(String eventTitle, String desc, String date, String venue, String image) { this.eventTitle = eventTitle; this.Desc = desc; this.date = date; this.venue = venue; this.image = image; } public UploadEventModel(){} public String getEventTitle() { return eventTitle; } public void setEventTitle(String eventTitle) { this.eventTitle = eventTitle; } public String getDesc() { return Desc; } public void setDesc(String desc) { Desc = desc; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } public String getVenue() { return venue; } public void setVenue(String venue) { this.venue = venue; } public String getImage() { return image; } public void setImage(String image) { this.image = image; } }
Logcat日志
2023-11-06 14:27:36.006 23637-23637 FirebaseData com.example.rsvpea D Data retrieved: 0
数据库JSON结构
{ "Events List": { "5 Nov 2023 20:43:57": { "date": "29 feb 2024", "desc": "birthday party for a batak", "eventTitle": "Batak Bday", "image": "url", "venue": "TMA Pai" }, "5 Nov 2023 23:12:29": { "date": "40 feb 2024 ", "desc": "event description sample", "eventTitle": "new event", "image": "url", "venue": "tma pai" }, "6 Nov 2023 00:28:28": { "date": "hhhs", "desc": "hshsh", "eventTitle": "hsha", "image": "url" } }, "Users": { "cN0Z4YQEeoXPQKYH0lYxQegpfFE2": { "mail": "ayu@awsm.ayu", "password": "hello123", "userName": "ayu" } } }
数据库规则
{ "rules": { ".read": true, // 2023-12-4 ".write": true, // 2023-12-4 } }
解决方案
1. 修正数据库路径名称
代码中使用的节点名称是"Event List",但数据库中实际节点是"Events List"(多了一个s),导致路径不匹配。修改Home.java中的路径:
database.getReference().child("Events List") // 把"Event List"改为"Events List"
2. 修正模型类字段映射
模型类中的Desc字段首字母大写,而数据库中对应的字段是小写的desc,Firebase序列化时严格匹配大小写,导致字段映射失败。有两种修复方式:
- 方式一:修改模型类字段名
将模型类中的Desc改为desc,同步更新getter/setter:private String eventTitle, desc, date, venue, image; public UploadEventModel(String eventTitle, String desc, String date, String venue, String image) { this.eventTitle = eventTitle; this.desc = desc; this.date = date; this.venue = venue; this.image = image; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } - 方式二:添加
@PropertyName注解
保留原字段名,通过注解指定数据库中的字段名:import com.google.firebase.database.PropertyName; @PropertyName("desc") private String Desc; @PropertyName("desc") public String getDesc() { return Desc; } @PropertyName("desc") public void setDesc(String desc) { Desc = desc; }
3. 数据加载后通知Adapter刷新
Firebase数据读取是异步操作,数据加载完成后需要通知Adapter更新,否则RecyclerView不会刷新。修改Home.java代码:
- 将Adapter声明为Activity成员变量,让
onDataChange可以访问 - 在
onDataChange中清空原有数据并通知Adapter更新
修改后的Home.java关键代码:
public class Home extends AppCompatActivity { // ... 其他成员变量 ... RecycleContentAdapter adapter; // 声明为成员变量 @Override protected void onCreate(Bundle savedInstanceState) { // ... 其他代码 ... ArrayList<TimelineCardContent> timelineCardContents = new ArrayList<>(); RecyclerView timeline = findViewById(R.id.timelineRecyclerView); timeline.setLayoutManager(new LinearLayoutManager(this)); // 初始化Adapter并设置给RecyclerView adapter = new RecycleContentAdapter(this, timelineCardContents); timeline.setAdapter(adapter); database=FirebaseDatabase.getInstance(); database.getReference().child("Events List").addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { timelineCardContents.clear(); // 清空旧数据,避免重复加载 for(DataSnapshot itemSnapshot : snapshot.getChildren()){ UploadEventModel temp = itemSnapshot.getValue(UploadEventModel.class); if(temp != null){ // 判空防止空指针 timelineCardContents.add(new TimelineCardContent(temp.getImage(), temp.getEventTitle())); } } Log.d("FirebaseData", "Data retrieved: " + timelineCardContents.size() + " items"); adapter.notifyDataSetChanged(); // 通知Adapter数据更新 } @Override public void onCancelled(@NonNull DatabaseError error) { Toast.makeText(Home.this, "Error", Toast.LENGTH_SHORT).show(); } }); // ... 其他代码 ... } }
4. 可选:添加调试日志排查
在onDataChange中添加日志,确认是否读取到数据库节点:
Log.d("FirebaseDebug", "节点是否存在:" + snapshot.exists()); Log.d("FirebaseDebug", "子节点数量:" + snapshot.getChildrenCount());
内容的提问来源于stack exchange,提问作者Ayushman Gupta
相关产品推荐
相关产品推荐

