Activity状态保存机制详解

一、临时状态保存(配置变更场景)

1. onSaveInstanceState机制

  • 触发时机

    • 配置变更(屏幕旋转、语言切换等)

    • 内存不足时后台Activity被回收

    • 不会在正常finish()时调用

  • 典型使用

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("KEY_USER_INPUT", editText.getText().toString());
        outState.putInt("KEY_SCROLL_POSITION", recyclerView.getScrollY());
    }

2. 数据恢复流程

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    if (savedInstanceState != null) {
        String userInput = savedInstanceState.getString("KEY_USER_INPUT");
        int scrollPos = savedInstanceState.getInt("KEY_SCROLL_POSITION");
        // 恢复UI状态...
    }
}

二、持久化状态保存

1. ViewModel保存

  • 优势

    • survives配置变更

    • 不依赖Bundle大小限制

      public class MyViewModel extends ViewModel {
          private MutableLiveData<String> userInput = new MutableLiveData<>();
          
          public LiveData<String> getUserInput() {
              return userInput;
          }
      }
      
      // Activity中使用
      viewModel.getUserInput().observe(this, input -> {
          editText.setText(input);
      });

2. 本地存储方案

存储方式适用场景示例
SharedPreferences简单键值对用户偏好设置
Room数据库结构化数据表单草稿保存
文件存储复杂对象/大数据图片缓存

三、自动状态保存的UI组件

1. 原生支持保存的View

  • EditText(文本内容/光标位置)

  • CheckBox/RadioButton(选中状态)

  • RecyclerView(滚动位置)

2. 自定义View实现

public class CustomView extends View {
    // 必须的ID设置
    public CustomView(Context context) {
        super(context);
        setId(View.generateViewId());
    }
    
    @Override
    protected Parcelable onSaveInstanceState() {
        Bundle bundle = new Bundle();
        bundle.putParcelable("superState", super.onSaveInstanceState());
        bundle.putInt("CUSTOM_STATE", customValue);
        return bundle;
    }
    
    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        Bundle bundle = (Bundle) state;
        super.onRestoreInstanceState(bundle.getParcelable("superState"));
        customValue = bundle.getInt("CUSTOM_STATE");
    }
}

四、状态保存最佳实践

  1. 分层保存策略

    • 瞬时UI状态 → onSaveInstanceState()

    • 短期数据 → ViewModel

    • 长期数据 → 持久化存储

  2. Bundle使用注意

    • 避免保存大对象(>1MB可能被系统丢弃)

    • 优先保存最小必要数据(如ID而非完整对象)

  3. 多Fragment场景

    // Fragment中设置
    setRetainInstance(true); // 保留非UI相关数据

五、常见问题解决方案

1. 状态未正确恢复

  • 检查点

    • 是否调用了super方法

    • View是否设置了android:id

    • 是否在setContentView之后恢复

2. 数据序列化问题

  • 复杂对象处理

    // 实现Parcelable
    public class User implements Parcelable {
        private String name;
        
        protected User(Parcel in) {
            name = in.readString();
        }
        
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(name);
        }
        
        public static final Creator<User> CREATOR = new Creator<User>() {
            @Override
            public User createFromParcel(Parcel in) {
                return new User(in);
            }
        };
    }

3. 异步加载冲突

// 使用isChangingConfigurations判断
if (!isChangingConfigurations()) {
    // 只有真正销毁时才释放资源
    releaseHeavyResource();
}

六、进阶回答技巧

  1. 系统原理层面
    Activity状态保存实际是通过ActivityThread维护的ActivityClientRecord实现的,当系统触发保存时,会通过Instrumentation.callActivityOnSaveInstanceState()回调到我们的Activity

  2. 架构设计层面
    在APP中,采用三级状态保存:

    • 购物车商品ID通过ViewModel保存

    • 搜索框文本通过onSaveInstanceState保存

    • 用户偏好通过SharedPreferences持久化

  3. 性能优化层面
    通过以下措施优化状态保存:

    • 延迟加载非关键视图(ViewStub)

    • 分页加载列表数据

    • 使用SavedStateRegistry替代部分Bundle操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值