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

Fragment中submitList加载Room数据后RecyclerView无显示问题

RecyclerView加载数据后仍为空的问题排查与解决

问题描述

运行应用后RecyclerView显示为空,日志中ItemCountOUTSIDE先输出且值为0,ItemCount后输出值为2(数据库内确实存在2条数据)。已确认Room数据库和ViewModel能正常获取数据(用同一个观察者可在TextView中显示数据),知晓观察者在独立线程执行导致滞后,但不清楚解决办法。

相关代码

Fragment代码

import android.content.Context;
import android.content.Intent;
import android.content.pm.LauncherActivityInfo;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

public class Frag1 extends Fragment {
    CustomViewModel viewModel;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.frag1_layout, container, false);

        viewModel = new ViewModelProvider(this).get(CustomViewModel.class);

        RecyclerView recyclerView = rootView.findViewById(R.id.rv1);
        final Adapter adapter = new Adapter(new Adapter.Diff());

        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

        viewModel.show().observe(getViewLifecycleOwner(), rEnts -> {
            adapter.submitList(rEnts);
            Log.d("ItemCount", String.valueOf(adapter.getItemCount()));
        });

        Log.d("ItemCountOUTSIDE", String.valueOf(adapter.getItemCount()));

        return rootView;
    }
}

Holder代码

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 org.w3c.dom.Text;

public class Holder extends RecyclerView.ViewHolder {
    private final TextView textView;

    private Holder(@NonNull View itemView) {
        super(itemView);
        textView = itemView.findViewById(R.id.textName);
    }

    public void bind(rEnt E){
        textView.setText(E.rN);
    }

    static Holder create(ViewGroup parent){
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.rv1_item, parent, false);
        return new Holder(view);
    }
}

Adapter代码

import android.util.Log;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListAdapter;
import androidx.recyclerview.widget.RecyclerView;
import androidx.room.Query;

import java.util.List;

public class Adapter extends ListAdapter<rEnt, Holder> {

    List<rEnt> myList = getCurrentList();

    public Adapter(@NonNull DiffUtil.ItemCallback<rEnt> diffCB){
        super(diffCB);
    }

    @NonNull
    @Override
    public Holder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return Holder.create(parent);
    }

    @Override
    public void onBindViewHolder(@NonNull Holder holder, int position) {
        rEnt currentEnt = getItem(position);
        holder.bind(currentEnt);
    }

    static class Diff extends DiffUtil.ItemCallback<rEnt>{ 

        @Override
        public boolean areItemsTheSame(@NonNull rEnt oldItem, @NonNull rEnt newItem) {
            return oldItem.getId() == newItem.getId();
        }

        @Override
        public boolean areContentsTheSame(@NonNull rEnt oldItem, @NonNull rEnt newItem) {
            return oldItem.rN.equals(newItem.rN);
        }
    }
}

解决方法

你的核心逻辑没问题,submitList会自动通知RecyclerView更新,空列表问题大概率是细节疏漏导致,按以下步骤排查:

  • 修正DiffUtil的ID比较逻辑
    如果rEnt的主键id是Long类型,不能用==比较(自动装箱会导致对象地址判断错误),改成equals:

    @Override
    public boolean areItemsTheSame(@NonNull rEnt oldItem, @NonNull rEnt newItem) {
        return oldItem.getId().equals(newItem.getId());
    }
    
  • 检查Item布局高度
    打开rv1_item.xml,确认根布局高度是wrap_content或固定值,若设为match_parent会导致item被挤压无法显示。

  • 移除无效的列表变量
    Adapter中List<rEnt> myList = getCurrentList();这行是在构造时初始化,后续submitList更新后该变量不会同步,直接删除即可,需要列表时用getCurrentList()或getItem(position)获取最新数据。

  • 验证观察者生命周期
    你已经使用getViewLifecycleOwner()绑定观察者,这是正确的,确保Fragment视图销毁时自动解绑,避免内存泄漏。

另外,日志中ItemCountOUTSIDE先输出是正常现象——Room数据库查询是异步操作,观察者回调要等查询完成才会执行,无需额外处理,只要submitList调用后RecyclerView能自动更新即可。如果以上步骤都排查过仍无效果,可以在submitList后临时添加adapter.notifyDataSetChanged()强制刷新(ListAdapter的submitList本应自动处理,这只是排查手段)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 06:54:06