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

Bottom Navigation切换Fragment后数据丢失问题求助(附代码)

解决Fragment切换后数据丢失的问题

我帮你分析了下问题所在,以及对应的解决方案:

问题根源

你遇到的核心问题有两个:

  1. Fragment切换时的视图销毁:你的setFragment方法用了replace,这个操作会把之前的Fragment视图完全销毁,切回Fragment A时会重新执行onCreateView。而你在onCreateView里每次都重新初始化herbalModels = new ArrayList<>()和kampoModels = new ArrayList<>(),直接清空了之前加载的数据。
  2. 异步请求的空白期:即使重新发起Volley请求,因为网络请求是异步的,界面会短暂空白,体验很差。

解决方案

1. 保留Fragment数据,避免重复初始化列表

把数据列表从onCreateView里的局部变量改成Fragment的成员变量,只在Fragment创建时初始化一次:

public class herbal extends Fragment { // 你的Fragment类
    // 把列表提升为成员变量,不要在onCreateView里重新new
    private ArrayList<herbalModel> herbalModels;
    private ArrayList<kampoModel> kampoModels;
    // 其他成员变量(适配器、RecyclerView等)...

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 只在Fragment创建时初始化一次列表
        herbalModels = new ArrayList<>();
        kampoModels = new ArrayList<>();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_herbal, container, false);
        // 删掉这两行:herbalModels = new ArrayList<>(); kampoModels = new ArrayList<>();
        // 剩下的原有逻辑...
        return rootView;
    }
}

2. 改用Hide/Show切换Fragment,避免视图销毁

修改MainActivity的setFragment方法,用hide和show替代replace,这样Fragment的视图和数据都会被保留,切换时只是隐藏/显示,不会重新创建:

首先在MainActivity里添加一个变量记录当前显示的Fragment:

private Fragment currentFragment;

然后修改初始化Fragment的逻辑:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if(isNetworkStatusAvialable (getApplicationContext())) {
        bottomNavigationView=(BottomNavigationView)findViewById(R.id.main_nav);
        frameLayout=(FrameLayout) findViewById(R.id.main_frame);
        
        // 初始化所有Fragment
        herbal= new herbal();
        crude = new crude();
        database=new database();
        analysis=new analysis();
        compound=new compound();
        
        // 初始化显示第一个Fragment
        currentFragment = herbal;
        getSupportFragmentManager().beginTransaction()
                .add(R.id.main_frame, herbal)
                .commit();
        
        bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
                switch (menuItem.getItemId()) {
                    case R.id.nav_herbal:
                        setFragment(herbal);
                        return true;
                    case R.id.nav_crude:
                        setFragment(crude);
                        return true;
                    case R.id.nav_database:
                        setFragment(database);
                        return true;
                    case R.id.nav_analysis:
                        setFragment(analysis);
                        return true;
                    case R.id.nav_compound:
                        setFragment(compound);
                        return true;
                    default:
                        return false;
                }
            }
        });
    } else {
        Toast.makeText(getApplicationContext(), "internet is not avialable", Toast.LENGTH_SHORT).show();
    }
}

最后修改setFragment方法:

private void setFragment(Fragment fragment) {
    FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
    
    // 隐藏当前显示的Fragment
    if (currentFragment != null) {
        fragmentTransaction.hide(currentFragment);
    }
    
    // 如果目标Fragment还没添加到容器,先添加;否则直接显示
    if (!fragment.isAdded()) {
        fragmentTransaction.add(R.id.main_frame, fragment);
    } else {
        fragmentTransaction.show(fragment);
    }
    
    fragmentTransaction.commit();
    currentFragment = fragment;
}

3. 优化请求逻辑,避免重复加载数据

在Fragment A的加载数据方法里,先判断列表是否已有数据,避免重复发起网络请求:

private void get20DataJamu() {
    // 如果已有数据,直接更新适配器,不用再请求
    if (!herbalModels.isEmpty()) {
        mAdapter.notifyDataSetChanged();
        return;
    }
    // 原有Volley请求代码...
}

private void get20DataKampo() {
    if (!kampoModels.isEmpty()) {
        kampoAdapter.notifyDataSetChanged();
        return;
    }
    // 原有Volley请求代码...
}

这样修改后,切换Fragment再切回来时,数据会完整保留,界面也不会出现空白,同时避免了不必要的网络请求。


内容的提问来源于stack exchange,提问作者Muhammad Ilham Ramadhan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:31:26