android onSaveInstance方法项目中的实践

onSaveInstance先做大概了解

onSaveInstance(Bundle outState)方法用于内存回收时,持久化数据用。

大多数app会直接改成内存回收后,直接重启app,这样也是有好处的:

  1. 免去再次打开时,先闪屏再加载数据。 体验不太好。
  2. 开发也便利,不需要记录状态,直接重启app,简单便捷

有优点必然就有缺点:

  1. 有些界面需要记录状态并在再次打开时恢复当时的状态,明显,这种实现直接被放弃了。

目前介绍数据持久化时遇到的问题

Activity 有两个onSaveInstance方法
@Override
protected void onSaveInstanceState(Bundle outState) {
  super.onSaveInstanceState(outState);
}
@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
  super.onSaveInstanceState(outState, outPersistentState);
}

Fragment 只有一个onSaveInstance方法
@Override
protected void onSaveInstanceState(Bundle outState) {
  super.onSaveInstanceState(outState);
}
复制代码
protected 对应的方法会在横竖屏切换、按Home键、第三方打开本地应用等操作下会调用。 Public 的不会。

遇到的问题及解决方案:

1、FragmentManager().beginTransaction()操作fragment时, 如果切换到后台一段时间后,内存被回收了,再次打开app, 界面恢复,会出现两个fragment重叠的问题。

原因:fragmentManager操作的fragment,会在内存销毁前,自动保存在(@Nullable Bundle savedInstanceState)中,再次打开后,会自动恢复fragment。 然后再次走oncreate方法,按顺序新建新的fragment,并被fragmentManager加入。这样就造成了重叠的两个fragment。
解决:
第一步、在fragmentmanager加入fragment时,设置tag
getSupportFragmentManager().beginTransaction()
   .add(getFragmentContentId(), fragment,tag)
    .commit();
复制代码
 第二步、在
protected void onCreate(@Nullable Bundle savedInstanceState) 方法中做相应处理

处理的方式有两种,一种就是恢复之前保存的,不做新建操作。
if (null != savedInstanceState) {
  if (null != getSupportFragmentManager().findFragmentByTag(BoxApiConstant.BOX_VIEW_PAGER_FRAGMENT_TAG)) {
    boxViewPagerFragment =
        (BoxViewPagerFragment) getSupportFragmentManager().findFragmentByTag(BoxApiConstant.BOX_VIEW_PAGER_FRAGMENT_TAG);
  }
}

 第二种就是直接去掉保存的,使用新建的。
 if (null != savedInstanceState) {
  if (null != getSupportFragmentManager().findFragmentByTag(BoxApiConstant.BOX_VIEW_PAGER_FRAGMENT_TAG)) {
    getSupportFragmentManager().beginTransaction()
 .remove(getSupportFragmentManager().findFragmentByTag(BoxApiConstant.BOX_VIEW_PAGER_FRAGMENT_TAG)).commitNow();
  }
}

复制代码

2、onSaveInstance并不是只有在内存回收时才调用, 横竖屏切换、按Home键、调用第三方程序时(比如调用第三方程序打开)也会走这个方法。但我们有时候并不需要上面三种情况下走onSaveInstance方法中的逻辑。

解决(个人的解决方法):
1. 使用一个boolean值,比如isBackShow,在调用onSaveInstance时就把isBackShow设置为true。
2. 如果此时的onSaveInstance并不是自己想要的,就在onResume方法中去掉这次保存,并把isBackShow设置为false
3. onResume方法中,加个判断条件
    if (isBackShow) {}
    
    加这个boolean值的原因是,如果内存并未被回收,则此场景并不是我们想要的恢复数据的场景,则去掉在onSaveInstance方法中保存的数据。如果内存被回收了,则isBackShow会在界面重回时被重置成默认值false,所以并不会走onresume方法中关于去掉保存值的逻辑。
复制代码

最后,贴上关于内存回收后,再次打开重启app的操作连接。

被回收后,重启APP

转载于:https://juejin.im/post/5a7908a05188257a60497608

你可能感兴趣的:(android onSaveInstance方法项目中的实践)