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

RecyclerView嵌套CardView结合Room使用初始不渲染需滚动后显示问题咨询

问题根因
  • 每次onBindViewHolder执行时都重复创建子适配器、布局管理器,导致子RecyclerView需要重复渲染,初始加载时父布局无法正确测量高度
  • LiveData异步返回子分类数据后,仅更新了子适配器,没有触发父RecyclerView重新测量当前项的尺寸,导致父项没有预留足够的展示空间,滚动后父布局重新测量才正常显示
  • ViewModel中getItemListByCat方法每次调用都会覆盖itemsForCat成员变量,多个父项同时查询时会出现数据错乱
  • 观察者绑定的是页面级生命周期,重复绑定会导致内存泄漏、旧数据回调覆盖新数据的问题
修复方案

1. 修正ViewModel逻辑

移除itemsForCat成员变量,每次查询直接返回独立的LiveData实例,避免多个查询互相覆盖:

public class SubCategoryModel extends AndroidViewModel {
    private SubCategoryRepository mySubCategoryRepository;
    private LiveData<List<sub_category>> allItems;

    public SubCategoryModel(Application application) {
        super(application);
        mySubCategoryRepository = new SubCategoryRepository(application);
        allItems = mySubCategoryRepository.getAllItems();
    }

    public LiveData<List<sub_category>> getAllItems() { 
        return allItems; 
    }

    // 移除成员变量存储,每次直接返回新的查询结果
    public LiveData<List<sub_category>> getItemListByCat(Integer catid) {  
        return mySubCategoryRepository.getItemListByCat(catid); 
    }
}

同理Repository中的itemsListByCat也可以改成局部变量,不需要作为成员变量存储。

2. 优化父Adapter绑定逻辑

将子RecyclerView的初始化逻辑移到onCreateViewHolder中,只执行一次,避免重复创建:

// 父Adapter构造方法中初始化ViewModel,不要每次onBind都获取
public ParentAdapter(Context context, Fragment fragment, List<category> categoryItems) {
    this.myFcontext = fragment;
    this.myCategoryItems = categoryItems;
    this.mySubCategoryModel = new ViewModelProvider(myFcontext).get(SubCategoryModel.class);
}

@Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.parent_item, parent, false);
    ItemViewHolder holder = new ItemViewHolder(view);
    // 子RecyclerView配置仅初始化一次
    holder.subRecyclerView.setLayoutManager(new LinearLayoutManager(parent.getContext(), RecyclerView.HORIZONTAL, false));
    holder.subRecyclerView.setHasFixedSize(true);
    // 子适配器仅初始化一次
    holder.subAdapter = new SubCategoryCardAdapter(parent.getContext(), myFcontext);
    holder.subRecyclerView.setAdapter(holder.subAdapter);
    return holder;
}

@Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
    category current = myCategoryItems.get(position);
    holder.textViewName.setText(current.Category);
    // 先给子适配器设置空占位,避免复用时显示旧数据
    holder.subAdapter.setItems(Collections.emptyList());
    // 观察当前分类的子数据,用holder作为观察者的生命周期Owner,避免重复绑定
    mySubCategoryModel.getItemListByCat(current.cat_id).observe(holder, sub_categoryList -> {
        holder.subAdapter.setItems(sub_categoryList);
        // 关键:更新数据后触发父项重新测量尺寸
        holder.itemView.requestLayout();
    });
}

// ViewHolder类实现LifecycleOwner接口,管理单个Item的观察生命周期
static class ItemViewHolder extends RecyclerView.ViewHolder implements LifecycleOwner {
    TextView textViewName;
    RecyclerView subRecyclerView;
    SubCategoryCardAdapter subAdapter;
    private final LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);

    public ItemViewHolder(View itemView) {
        super(itemView);
        textViewName = itemView.findViewById(R.id.category_name);
        subRecyclerView = itemView.findViewById(R.id.sub_recycler);
    }

    @Override
    public Lifecycle getLifecycle() {
        return lifecycleRegistry;
    }

    // 绑定的时候标记生命周期为STARTED
    void bind() {
        lifecycleRegistry.setCurrentState(Lifecycle.State.STARTED);
    }

    // 回收的时候标记生命周期为DESTROYED,自动移除观察者
    void recycle() {
        lifecycleRegistry.setCurrentState(Lifecycle.State.DESTROYED);
    }
}

// 父Adapter中重写对应方法,管理ViewHolder生命周期
@Override
public void onViewRecycled(@NonNull ItemViewHolder holder) {
    super.onViewRecycled(holder);
    holder.recycle();
}

@Override
public void onBindViewHolder(@NonNull ItemViewHolder holder, int position, @NonNull List<Object> payloads) {
    super.onBindViewHolder(holder, position, payloads);
    holder.bind();
}

3. 可选优化

给子RecyclerView设置最小高度,或者在父Item布局中给子RecyclerView预留默认高度,避免初始加载时高度为0导致的视觉闪烁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 08:45:11