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

Android:Activity中Fragment的状态保存与恢复需求

解决方案:恢复到上次显示的Fragment状态

咱们先梳理下现有代码里影响状态恢复的几个问题:

  • onCreate里不管有没有保存的状态,都直接初始化intro1,导致每次重启Activity都会回到第一个Fragment;
  • 静态变量fragment、fragmentManager、fragmentTransaction容易引发内存泄漏,还没法准确跟踪当前显示的Fragment;
  • onSaveInstanceState里保存的fragment不一定是当前正在显示的实例,恢复时容易出错。

下面是修改后的完整代码和关键改动说明:

1. 重构IntroductionActivity代码

public class IntroductionActivity extends AppCompatActivity implements View.OnClickListener { 
    private static final String TAG = "IntroductionActivity";
    // 用成员变量跟踪当前Fragment,替换原来的静态变量
    private Fragment currentFragment;
    private static final String KEY_CURRENT_FRAG_TAG = "current_fragment_tag";
    private String currentFragmentTag;

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_introduction); 

        ActionBar actionbar = getSupportActionBar();

        if (savedInstanceState != null) {
            // 从保存的状态中读取上次的Fragment标签
            currentFragmentTag = savedInstanceState.getString(KEY_CURRENT_FRAG_TAG);
            // 通过标签获取已保存的Fragment实例
            currentFragment = getSupportFragmentManager().findFragmentByTag(currentFragmentTag);
        } 

        // 没有保存状态时,默认加载第一个Fragment
        if (currentFragment == null) {
            currentFragment = new Intro1();
            currentFragmentTag = "intro1";
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.fragment_container, currentFragment, currentFragmentTag)
                    .commit();
        }
    } 

    @Override 
    protected void onSaveInstanceState(Bundle outState) { 
        super.onSaveInstanceState(outState); 
        // 保存当前Fragment的标签,比直接存Fragment实例更稳定
        outState.putString(KEY_CURRENT_FRAG_TAG, currentFragmentTag);
    } 

    @Override 
    public void onClick(View v) { 
        // 按需添加其他点击逻辑
    } 

    // 改成非静态方法,避免静态引用带来的问题
    public void switchToIntro2() {
        currentFragment = new Intro2();
        currentFragmentTag = "intro2";
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.fragment_container, currentFragment, currentFragmentTag)
                .commit();
    }
}

2. 修改Intro1 Fragment代码

把原来调用静态方法的逻辑改成通过Activity实例调用:

public class Intro1 extends Fragment{ 
    private View rootView; 
    private Button intro1nxtButton; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
        rootView = inflater.inflate(R.layout.fragment_intro_1, container, false); 
        intro1nxtButton = rootView.findViewById(R.id.intro1Next_button); 
        intro1nxtButton.setOnClickListener(new View.OnClickListener() { 
            @Override 
            public void onClick(View v) { 
                // 强转为宿主Activity,调用切换Fragment的方法
                ((IntroductionActivity) getActivity()).switchToIntro2();
            } 
        }); 
        return rootView; 
    } 
}

3. 关键改动说明

  • 移除静态变量:静态引用会长期持有Activity实例,容易引发内存泄漏,改用成员变量+Fragment标签的方式跟踪状态;
  • 正确恢复状态:启动Activity时先检查savedInstanceState,如果存在就恢复上次显示的Fragment,不存在才加载默认的Intro1;
  • 保存Fragment标签:在onSaveInstanceState中保存当前Fragment的标签,比直接序列化Fragment实例更稳定,避免序列化异常;
  • 非静态方法切换Fragment:把原来的静态doStuff改成Activity的成员方法,通过Fragment获取宿主Activity实例调用,更符合Android组件生命周期规范。

这样修改后,不管是按下返回键关闭Activity,还是因配置变更重启Activity,再次打开时都会自动恢复到上次显示的Fragment(比如Intro2),而不是回到初始的Intro1。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:50:08