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

Android:解决Fragment B传对象后Fragment A列表新增项丢失问题

嘿,我来帮你解决这个问题!你遇到的情况确实是因为每次从Fragment B切回Fragment A时,A都会被重新实例化,导致之前添加的列表项被初始数据覆盖了。下面是具体的问题分析和解决方案:

问题根源

每次你在Fragment B里调用replace(R.id.FLfragment, fragment)回到Fragment A时,系统都会创建一个全新的Registration实例,而不是复用之前的那个。新实例会执行onCreateView里的createSubjectList()方法,把subjectlist重新初始化为只有person1和person2的列表,之前添加的person3、person4自然就被覆盖消失了。

解决方案

这里提供两种最适合新手的靠谱方案,你可以根据自己的需求选择:

方案一:用ViewModel保存列表数据(推荐,符合Android架构规范)

ViewModel专门用来在Fragment/Activity重建时保存数据,不会因为生命周期变化丢失内容,是Android官方推荐的持久化临时数据的方式。

  1. 先创建一个SubjectViewModel类:
import androidx.lifecycle.ViewModel;
import java.util.ArrayList;
import java.util.List;

public class SubjectViewModel extends ViewModel {
    private List<subjects> subjectList;

    public List<subjects> getSubjectList() {
        if (subjectList == null) {
            subjectList = new ArrayList<>();
            // 初始化默认数据
            subjectList.add(new subjects("person1",23,52,160));
            subjectList.add(new subjects("person2",23,80,180));
        }
        return subjectList;
    }

    public void addSubject(subjects newSubject) {
        subjectList.add(newSubject);
    }
}
  1. 修改Fragment A(Registration)的关键代码:
  • 移除原来的createSubjectList()方法,改用ViewModel获取列表
  • 修复notifyItemInserted的位置参数(你之前写的0是添加到开头,要改成列表末尾的索引)

修改后的Registration核心代码:

public class Registration extends Fragment {
    private RecyclerView recyclerView;
    private SubjectAdapter msubjectadapter;
    private SubjectViewModel viewModel; // 新增ViewModel实例
    private Button btn_addsubject;

    public Registration() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 获取ViewModel,确保数据在重建时保留
        viewModel = new ViewModelProvider(this).get(SubjectViewModel.class);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View FragmentView = inflater.inflate(R.layout.fragment_registeration, container, false);
        btn_addsubject= (Button) FragmentView.findViewById(R.id.addsubject);
        btn_addsubject.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                newsubject NewSubject = new newsubject();
                FragmentTransaction transaction= getFragmentManager().beginTransaction();
                transaction.replace(R.id.FLfragment,NewSubject);
                transaction.addToBackStack(null);
                transaction.commit();
            }
        });

        // 从ViewModel获取持久化的列表
        List<subjects> subjectlist = viewModel.getSubjectList();
        buildRecyclerView(FragmentView, subjectlist);

        msubjectadapter.SetOnClickListener(new SubjectAdapter.OnClickItemListener() {
            @Override
            public void onItemClick(int position) {
                Toast.makeText(getActivity(), "You clicked " + subjectlist.get(position).getName() + " on row number " + position, Toast.LENGTH_SHORT).show();
            }
        });
        return FragmentView;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Bundle bundle = this.getArguments();
        if (bundle != null) {
            subjects s = (subjects) bundle.getParcelable("subj");
            Toast.makeText(getActivity(), ""+s.getHeight() + s.getName() + s.getAge() +s.getWeight(), Toast.LENGTH_SHORT).show();
            // 通过ViewModel添加新数据
            viewModel.addSubject(s);
            // 通知适配器在列表末尾插入新项
            msubjectadapter.notifyItemInserted(viewModel.getSubjectList().size() - 1);
        }
    }

    // 修改buildRecyclerView,接收外部传入的列表
    public void buildRecyclerView(View FView, List<subjects> subjectlist){
        recyclerView = (RecyclerView) FView.findViewById(R.id.subjects);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(FView.getContext()));
        msubjectadapter= new SubjectAdapter(subjectlist);
        recyclerView.setAdapter(msubjectadapter);
    }
}

方案二:用hide/show替代replace切换Fragment(适合简单场景)

如果你不想引入ViewModel,可以通过隐藏原有Fragment、显示新Fragment的方式,让Fragment A不被销毁,从而保留列表数据。

  1. 修改Fragment A跳转到B的代码:
btn_addsubject.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        newsubject NewSubject = new newsubject();
        FragmentTransaction transaction= getFragmentManager().beginTransaction();
        // 隐藏当前Fragment A,添加Fragment B到容器
        transaction.hide(Registration.this);
        transaction.add(R.id.FLfragment, NewSubject);
        transaction.addToBackStack(null);
        transaction.commit();
    }
});
  1. 修改Fragment B返回A的代码:
btn_add.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // 先做输入校验,避免空指针
        String name = et_name.getText().toString().trim();
        String ageStr = et_age.getText().toString().trim();
        String weightStr = et_weight.getText().toString().trim();
        String heightStr = et_height.getText().toString().trim();
        if(TextUtils.isEmpty(name) || TextUtils.isEmpty(ageStr) || TextUtils.isEmpty(weightStr) || TextUtils.isEmpty(heightStr)){
            Toast.makeText(getActivity(), "请填写完整信息", Toast.LENGTH_SHORT).show();
            return;
        }

        subjects subject=new subjects(name,Integer.parseInt(ageStr),Integer.parseInt(weightStr),Integer.parseInt(heightStr));
        
        // 获取之前隐藏的Registration实例
        Registration fragment = (Registration) getFragmentManager().findFragmentByTag("REGISTRATION_TAG");
        if(fragment != null){
            // 直接调用A的方法添加数据
            fragment.addNewSubject(subject);
            // 返回上一页,显示原来的Fragment A
            getFragmentManager().popBackStack();
        }
    }
});
  1. 在Fragment A中添加方法并设置tag:
    首先在Activity中添加Registration时设置tag(或者在A自己的创建逻辑里设置):
// Activity中的代码示例
getSupportFragmentManager().beginTransaction()
    .add(R.id.FLfragment, new Registration(), "REGISTRATION_TAG")
    .commit();

然后在Registration中添加添加新数据的方法:

public void addNewSubject(subjects newSubject){
    subjectlist.add(newSubject);
    msubjectadapter.notifyItemInserted(subjectlist.size()-1);
}

额外小提醒

  • Java类名首字母要大写,你的subjects建议改成Subjects,符合命名规范
  • 获取EditText输入值时一定要做非空和有效性校验,避免崩溃

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 17:57:38