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

RecyclerView列表项中FragmentTransaction仅作用于首个元素问题

问题:RecyclerView列表项中FragmentContainerView加载Fragment异常

在RecyclerView适配器的onCreateViewHolder()方法中加载包含FragmentContainerView的布局后,尝试为每个列表项的容器添加不同Fragment时,出现所有Fragment内容仅显示在首个列表项的容器中的异常。

相关代码

列表项布局:listitem_layout.xml

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#D47F00">

  <androidx.fragment.app.FragmentContainerView
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

适配器onCreateViewHolder方法

@NonNull
@Override
public CustomHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View itemView = inflater.inflate(R.layout.listitem_layout, parent, false);
    return new CustomHolder(itemView, (AppCompatActivity) inflater.getContext());
}

CustomHolder实现

class CustomHolder extends RecyclerView.ViewHolder {
    public static boolean skip = true;
    private AppCompatActivity appCompatActivity;
    private FragmentContainerView fragmentContainerView;
    private Fragment attributeDetailFragment;
    private Trainer trainer;
    private TextView trainerAge;

    CustomHolder(@NonNull View itemView, AppCompatActivity appCompatActivity) {
        super(itemView);
        this.trainerAge = itemView.findViewById(R.id.trainer_age);
        this.fragmentContainerView = itemView.findViewById(R.id.fragment_container);
        this.appCompatActivity = appCompatActivity;
    }

    void setTrainer(Trainer trainer) {
        this.trainer = trainer;
        this.trainerAge.setText(" " + trainer.getAge());
        this.trainerAge.setOnClickListener(this::onTrainerAgeClick);
        itemView.setTag(this);
    }

    private void onTrainerAgeClick(View view) {
        attributeDetailFragment = new AgeFragment();
        showFragment();
    }

    private void showFragment() {
        Bundle args = new Bundle();
        args.putParcelable("trainer", trainer);
        attributeDetailFragment.setArguments(args);
        FragmentManager fragmentManager = appCompatActivity.getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(fragmentContainerView.getId(), attributeDetailFragment);
        fragmentTransaction.commit();
    }
}

问题原因

所有列表项的FragmentContainerView使用了同一个固定id(R.id.fragment_container),而FragmentManager是通过id来定位容器的。调用replace()时,FragmentManager会找到布局中第一个匹配该id的容器,也就是首个列表项的FragmentContainerView,因此所有Fragment都会被替换到这个容器中。

解决方案

方案1:为每个容器设置唯一id

在onCreateViewHolder中,为每个加载的FragmentContainerView生成唯一id,避免id冲突:

@NonNull
@Override
public CustomHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View itemView = inflater.inflate(R.layout.listitem_layout, parent, false);
    FragmentContainerView container = itemView.findViewById(R.id.fragment_container);
    // 生成唯一id
    container.setId(View.generateViewId());
    return new CustomHolder(itemView, (AppCompatActivity) inflater.getContext());
}

方案2:直接传入容器实例(AndroidX Fragment 1.2.0+)

从AndroidX Fragment 1.2.0版本开始,FragmentTransaction支持直接传入FragmentContainerView实例,无需依赖id定位:

private void showFragment() {
    Bundle args = new Bundle();
    args.putParcelable("trainer", trainer);
    attributeDetailFragment.setArguments(args);
    FragmentManager fragmentManager = appCompatActivity.getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    // 直接传入容器实例
    fragmentTransaction.replace(fragmentContainerView, attributeDetailFragment);
    fragmentTransaction.commit();
}

额外注意事项

  • RecyclerView存在列表项复用机制,需在onBindViewHolder中处理Fragment的状态恢复或清理,避免复用导致的显示异常。
  • 若列表项数量较多,频繁创建Fragment可能影响性能,可考虑用动态切换View的方式替代Fragment,减少实例创建开销。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 03:31:06