You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 00:44:58