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

Nested RecyclerView+Firebase调用push()插入数据时报反序列化错误

嵌套RecyclerView对接Firebase反序列化报错修复

问题现象

实现嵌套RecyclerView对接Firebase Realtime Database时,调用push()方法添加数据后,读取数据抛出如下错误:

Expected a List while deserializing, but got a class java.util.HashMap

问题相关原代码

MainActivity核心逻辑

AlertDialog dialog;
IFirebaseLoadListener iFirebaseLoadListener;

RecyclerView my_recycler_view;
DatabaseReference myData;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    myData= FirebaseDatabase.getInstance().getReference("MyData");
    dialog= new SpotsDialog.Builder().setContext(this).build();

    iFirebaseLoadListener = this;

    // 初始化视图
    my_recycler_view= (RecyclerView)findViewById(R.id.my_recycler_view);
    my_recycler_view.setHasFixedSize(true);
    my_recycler_view.setLayoutManager(new LinearLayoutManager(this));

    // 加载数据
    getFirebaseData();
}

private void getFirebaseData() {
    dialog.show();
    myData.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            List<itemGroup> itemGroups= new ArrayList<>();
            for(DataSnapshot groupSnapshot: dataSnapshot.getChildren())
            {
                itemGroup itemGroup= new itemGroup();

                itemGroup.setHeaderTitle(groupSnapshot.child("headerTitle").getValue(true).toString());
                GenericTypeIndicator<ArrayList<itemData>> genericTypeIndicator= new GenericTypeIndicator<ArrayList<itemData>>(){} ;
                // 此处存在未定义key变量、直接强转ArrayList的错误
                itemGroup.setListItem(groupSnapshot.child("listItem").child(key).getValue(genericTypeIndicator));
                itemGroups.add(itemGroup);
            }
            iFirebaseLoadListener.onFirebaseLoadSuccess(itemGroups);
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
            iFirebaseLoadListener.onFirebaseLoadFailed(databaseError.getMessage());
        }
    });
}

@Override
public void onFirebaseLoadSuccess(List<itemGroup> itemGroupList) {
    MyItemGroupAdapter adapter = new MyItemGroupAdapter(this,itemGroupList);
    my_recycler_view.setAdapter(adapter);
    dialog.dismiss();
}

@Override
public void onFirebaseLoadFailed(String message) {
    Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
    dialog.dismiss();
}

实体类定义

public class itemData {
    private String name ,image;

    public itemData() {}

    public itemData(String name, String image) {
        this.name = name;
        this.image = image;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getImage() {
        return image;
    }

    public void setImage(String image) {
        this.image = image;
    }
}

public class itemGroup {
    private String headerTitle;
    private ArrayList<itemData> listItem;

    public itemGroup() {}

    public itemGroup(String headerTitle, ArrayList<itemData> listItem) {
        this.headerTitle = headerTitle;
        this.listItem = listItem;
    }

    public String getHeaderTitle() {
        return headerTitle;
    }

    public void setHeaderTitle(String headerTitle) {
        this.headerTitle = headerTitle;
    }

    public ArrayList<itemData> getListItem() {
        return listItem;
    }

    public void setListItem(ArrayList<itemData> listItem) {
        this.listItem = listItem;
    }
}

适配器代码

public class MyItemAdapter extends RecyclerView.Adapter<MyItemAdapter.MyViewHolder> {
    private Context context;
    private List<itemData> itemDataList;

    public MyItemAdapter(Context context, List<itemData> itemDataList) {
        this.context = context;
        this.itemDataList = itemDataList;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View itemView = LayoutInflater.from(context).inflate(R.layout.layout_item,viewGroup,false);
        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder myViewHolder, int i) {
        myViewHolder.txt_item_titles.setText(itemDataList.get(i).getName());
        Picasso.get().load(itemDataList.get(i).getImage()).into(myViewHolder.img_item);

        myViewHolder.setiItemClickListener(new IItemClickListener() {
            @Override
            public void onItemClickListener(View view, int i) {
                Toast.makeText(context, ""+ itemDataList.get(i).getName(), Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public int getItemCount() {
        return (itemDataList != null ? itemDataList.size() : 0);
    }

    public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        TextView txt_item_titles;
        ImageView img_item;
        IItemClickListener iItemClickListener;

        public void setiItemClickListener(IItemClickListener iItemClickListener) {
            this.iItemClickListener = iItemClickListener;
        }

        public MyViewHolder (View itemView ){
            super(itemView);
            txt_item_titles= (TextView)itemView.findViewById(R.id.tvTitle);
            img_item= (ImageView) itemView.findViewById(R.id.itemImage);
            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            iItemClickListener.onItemClickListener(v,getAdapterPosition());
        }
    }
}

public class MyItemGroupAdapter extends RecyclerView.Adapter<MyItemGroupAdapter.MyViewHolder> {
    private Context context;
    private List<itemGroup> dataList;

    public MyItemGroupAdapter(Context context, List<itemGroup> dataList) {
        this.context = context;
        this.dataList = dataList;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
       View itemView = LayoutInflater.from(context).inflate(R.layout.layout_group,viewGroup,false);
       return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(@NonNull final MyViewHolder myViewHolder, int i) {
        myViewHolder.item_title.setText(dataList.get(i).getHeaderTitle());
        List<itemData> itemData = dataList.get(i).getListItem();
        MyItemAdapter itemListAdapter=new MyItemAdapter(context,itemData);
        myViewHolder.recycler_view_item_list.setHasFixedSize(true);
        myViewHolder.recycler_view_item_list.setLayoutManager(new LinearLayoutManager(context,LinearLayoutManager.HORIZONTAL,false));
        myViewHolder.recycler_view_item_list.setAdapter(itemListAdapter);
        myViewHolder.recycler_view_item_list.setNestedScrollingEnabled(false);

        myViewHolder.btn_more.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(context, "Button More "+ myViewHolder.item_title.getText(), Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public int getItemCount() {
        return (dataList != null ? dataList.size() : 0);
    }

    public class MyViewHolder extends RecyclerView.ViewHolder{
        TextView item_title ;
        RecyclerView recycler_view_item_list;
        Button btn_more;

        public MyViewHolder (View itemView ){
            super (itemView);
            item_title= (TextView) itemView.findViewById(R.id.itemTitle);
            btn_more= (Button)itemView.findViewById(R.id.btMore);
            recycler_view_item_list= (RecyclerView)itemView.findViewById(R.id.recycler_view_list);
        }
    }
}

报错根因

  • Firebase Realtime Database 底层没有数组/List类型的存储结构,当调用push()方法添加子节点时,Firebase会自动生成随机字符串作为节点key,此时listItem节点下的结构实际是key为pushID、value为itemData对象的HashMap结构,不是有序数组结构。
  • 原代码直接使用GenericTypeIndicator<ArrayList<itemData>>尝试将HashMap结构直接反序列化为ArrayList,触发类型不匹配错误。
  • 原代码中groupSnapshot.child("listItem").child(key)的key变量未定义,本身存在逻辑错误。

修复方案

修改getFirebaseData()方法中读取listItem的逻辑,不要直接强转ArrayList,手动遍历listItem下的所有子节点,逐个转换为itemData对象后组装为ArrayList,修复后的核心代码如下:

@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
    List<itemGroup> itemGroups= new ArrayList<>();
    for(DataSnapshot groupSnapshot: dataSnapshot.getChildren())
    {
        itemGroup itemGroup= new itemGroup();
        itemGroup.setHeaderTitle(groupSnapshot.child("headerTitle").getValue(true).toString());
        
        // 手动遍历listItem节点组装列表
        ArrayList<itemData> itemList = new ArrayList<>();
        for (DataSnapshot itemSnapshot : groupSnapshot.child("listItem").getChildren()) {
            itemData data = itemSnapshot.getValue(itemData.class);
            itemList.add(data);
        }
        itemGroup.setListItem(itemList);
        itemGroups.add(itemGroup);
    }
    iFirebaseLoadListener.onFirebaseLoadSuccess(itemGroups);
}

注:类名建议遵循Java大驼峰命名规范,将itemGroup、itemData改为ItemGroup、ItemData,避免后续出现类识别相关问题。

内容的提问来源于stack exchange,提问作者Alexandru Sirbu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 19:06:22