这个问题,其实不是太好复现。因为在android的缓存Fragment机制是写在androidx的库中。
主要的原因是android Framework机制:
at yourpackage.onSaveInstanceState(XXXActivity.kt:118)
at android.app.Activity.performSaveInstanceState(Activity.java:2283)
at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1508)
at android.app.ActivityThread.callActivityOnSaveInstanceState(ActivityThread.java:5878)
at android.app.ActivityThread.callActivityOnStop(ActivityThread.java:5281)
at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:5247)
at android.app.ActivityThread.handleStopActivity(ActivityThread.java:5312)
at android.app.servertransaction.StopActivityItem.execute(StopActivityItem.java:43)
at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:45)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:17
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2259)
主要流程:
ActivityThread->onPause|onStop|performDestroyActivity|callActivityOnStop|handleRelaunchActivity
Instrumentation-> callActivityOnSaveInstanceState
activity->onSaveInstanceState
即,当activity发生了需要停止和隐藏的时候,或者Relaunch等等情况,根据具体的尝尽是否进行保存。因为大部分情况是不会触发的。
只要后台不做app保活的情况,手机内存回收的情况等才会触发。
然后onSaveInstanceState就到app代码+androidx库代码了,不同的androidx版本或者之前的android.support版本是不同的:
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
//val e = Exception()
//e.printStackTrace()
}
这个是你自己的activity。然后调用super。即追溯到
androidx:activity库 ComponentActivity,
androidx:savestate库 SavedStateRegistryController | SavedStateRegistry.performSave,
outBundle.putBundle(SAVED_COMPONENTS_KEY, components) //“androidx.lifecycle.BundlableSavedStateRegistry.key”
接着,就是FragmentAcitvity的FragmentManager,对于SavedStateRegistry的注册。将
//SAVED_STATE_TAG = "android:support:fragments";
registry.registerSavedStateProvider(SAVED_STATE_TAG, () -> {
return saveAllStateInternal();//里面进行缓存Fragment
}
);
总结就是framework提供了暂存的触发条件,app的库内部支持了缓存机制。
其实更重要的是:你平时无法复现,而测试或者用户出现了。
这里提供几个思路:
val e = Exception()
e.printStackTrace()
可以十分方便的看到framework-androidx的代码逻辑。修改方案如下:
override fun onSaveInstanceState(outState: Bundle, outPersistentState: PersistableBundle) {
super.onSaveInstanceState(outState, outPersistentState)
removeCachedFragments(outState)
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
removeCachedFragments(outState)
}
private fun removeCachedFragments(outState: Bundle) {
if (false) { //非androidx 自行根据情况开启。
outState.putParcelable("android:support:fragments", null)
outState.putParcelable("android:fragments", null)
} else { //androidx
outState.getBundle("androidx.lifecycle.BundlableSavedStateRegistry.key")?.let {
it.remove("android:support:fragments")
it.remove("android:fragments")
}
}
}
其他:
三星手机还有一个问题,当关闭应用管理-蓝牙权限,app会立刻死掉进程。然后拉起的是你最后的activity。
如果你有一些初始化逻辑放在SplashActivity或者前置的一些地方,则会导致初始化不正常。
所以需要考虑将一些逻辑放到application的初始化中去。