“不保留活动”和配置更改之间有什么区别?

时间:2019-09-18 15:15:28

标签: android android-lifecycle android-viewmodel

我正在使用View Model体系结构组件来处理UI状态并包含业务逻辑。众所周知,它可以在配置更改后幸存下来,但是在“开发人员”选项中启用了“不保留活动”选项时,将创建一个新的View Model实例。在这两种情况下都将调用onDestroy活动,那么两者之间有什么区别?

我在View模型中维护状态机,并且由于View模型无法幸免,因此在恢复状态机时遇到了问题。我无法使用实例状态,因为它具有复杂的对象。

以下日志来自我尝试过的示例项目。它有一个活动TestActivity,其中包含一个片段TestFragment,而TestFragment包含两个片段TestStateAFragmentTestStateBFragment

TestActivity.kt

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_test)

    if(savedInstanceState == null) {
        supportFragmentManager.beginTransaction()
            .add(R.id.container_fragment_test, TestFragment())
            .commitAllowingStateLoss()
    }
}

TestFragment.kt

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    Timber.i("onViewCreated")
    super.onViewCreated(view, savedInstanceState)
    if(savedInstanceState == null) {
        childFragmentManager.beginTransaction()
            .add(R.id.container_state_a, TestStateAFragment.newInstance())
            .commitAllowingStateLoss()
        childFragmentManager.beginTransaction()
            .add(R.id.container_state_b, TestStateBFragment.newInstance())
            .commitAllowingStateLoss()
    }
}

TestStateAFragment.kt

private val compositeDisposable: CompositeDisposable = CompositeDisposable()
private lateinit var viewModel : TestStateAViewModel

override fun onCreate(savedInstanceState: Bundle?) {
    Timber.i("onCreate")
    super.onCreate(savedInstanceState)

    viewModel = ViewModelProviders.of(this, TestStateAViewModelFactory())
        .get(TestStateAViewModel::class.java)
    Timber.i(viewModel.toString())
}

屏幕旋转:

(TestStateAFragment.kt:101)#onPause: onPause
(TestStateBFragment.kt:66)#onPause: onPause
(TestFragment.kt:72)#onPause: onPause
(TestActivity.kt:45)#onPause: onPause
(TestStateAFragment.kt:105)#onStop: onStop
(TestStateBFragment.kt:70)#onStop: onStop
(TestFragment.kt:76)#onStop: onStop
(TestActivity.kt:50)#onStop: onStop
(TestActivity.kt:23)#onSaveInstanceState: onSaveInstanceState
(TestFragment.kt:55)#onSaveInstanceState: onSaveInstanceState
(TestStateAFragment.kt:55)#onSaveInstanceState: onSaveInstanceState
(TestActivity.kt:54)#onDestroy: onDestroy
(TestStateAFragment.kt:110)#onDestroyView: onDestroyView
(TestStateBFragment.kt:75)#onDestroyView: onDestroyView
(TestFragment.kt:81)#onDestroyView: onDestroyView
(TestStateAFragment.kt:115)#onDestroy: onDestroy
(TestStateBFragment.kt:80)#onDestroy: onDestroy
(TestFragment.kt:86)#onDestroy: onDestroy
(TestFragment.kt:17)#onAttach: onAttach
(TestFragment.kt:18)#onAttach: TestFragment{984b690 (625e084e-68d8-46d6-9527-dfe2694fa5c1) id=0x7f07004c}
(TestFragment.kt:23)#onCreate: onCreate
(TestStateAFragment.kt:30)#onAttach: onAttach
(TestStateAFragment.kt:31)#onAttach: TestStateAFragment{1ff9e9a (f73d9a4a-4fb0-4e1c-b6b0-220941525ae2) id=0x7f07004d}
(TestStateAFragment.kt:39)#onCreate: onCreate
(TestStateAFragment.kt:44)#onCreate: com.example.lifecycleviewmodel.fragment.states.a.TestStateAViewModel@afc805d
(TestStateBFragment.kt:27)#onAttach: onAttach
(TestStateBFragment.kt:28)#onAttach: TestStateBFragment{908b1a7 (a5fa2bce-9b3b-4474-ae2a-0a891f289f65) id=0x7f07004e}
(TestStateBFragment.kt:33)#onCreate: onCreate
(TestActivity.kt:34)#onStart: onStart
(TestFragment.kt:34)#onCreateView: onCreateView
(TestFragment.kt:40)#onViewCreated: onViewCreated
(TestStateAFragment.kt:67)#onCreateView: onCreateView
(TestStateAFragment.kt:73)#onViewCreated: onViewCreated
(TestStateBFragment.kt:44)#onCreateView: onCreateView
(TestStateBFragment.kt:50)#onViewCreated: onViewCreated
(TestFragment.kt:61)#onStart: onStart
(TestStateAFragment.kt:90)#onStart: onStart
(TestStateBFragment.kt:55)#onStart: onStart
(TestActivity.kt:40)#onResume: onResume
(TestFragment.kt:66)#onResume: onResume
(TestStateAFragment.kt:95)#onResume: onResume
(TestStateBFragment.kt:60)#onResume: onResume

不要停止活动:

(TestStateAFragment.kt:101)#onPause: onPause
(TestStateBFragment.kt:66)#onPause: onPause
(TestFragment.kt:72)#onPause: onPause
(TestActivity.kt:45)#onPause: onPause
(TestStateAFragment.kt:105)#onStop: onStop
(TestStateBFragment.kt:70)#onStop: onStop
(TestFragment.kt:76)#onStop: onStop
(TestActivity.kt:50)#onStop: onStop
(TestActivity.kt:23)#onSaveInstanceState: onSaveInstanceState
(TestFragment.kt:55)#onSaveInstanceState: onSaveInstanceState
(TestStateAFragment.kt:55)#onSaveInstanceState: onSaveInstanceState
(TestActivity.kt:30)#onRestart: onRestart
(TestActivity.kt:34)#onStart: onStart
(TestFragment.kt:61)#onStart: onStart
(TestStateAFragment.kt:90)#onStart: onStart
(TestStateBFragment.kt:55)#onStart: onStart
(TestActivity.kt:40)#onResume: onResume
(TestFragment.kt:66)#onResume: onResume
(TestStateAFragment.kt:95)#onResume: onResume
(TestStateBFragment.kt:60)#onResume: onResume
(TestStateAFragment.kt:101)#onPause: onPause
(TestStateBFragment.kt:66)#onPause: onPause
(TestFragment.kt:72)#onPause: onPause
(TestActivity.kt:45)#onPause: onPause
(TestStateAFragment.kt:105)#onStop: onStop
(TestStateBFragment.kt:70)#onStop: onStop
(TestFragment.kt:76)#onStop: onStop
(TestActivity.kt:50)#onStop: onStop
(TestActivity.kt:23)#onSaveInstanceState: onSaveInstanceState
(TestFragment.kt:55)#onSaveInstanceState: onSaveInstanceState
(TestStateAFragment.kt:55)#onSaveInstanceState: onSaveInstanceState

不要继续进行活动:

(TestStateAFragment.kt:101)#onPause: onPause
(TestStateBFragment.kt:66)#onPause: onPause
(TestFragment.kt:72)#onPause: onPause
(TestActivity.kt:45)#onPause: onPause
(TestStateAFragment.kt:105)#onStop: onStop
(TestStateBFragment.kt:70)#onStop: onStop
(TestFragment.kt:76)#onStop: onStop
(TestActivity.kt:50)#onStop: onStop
(TestActivity.kt:23)#onSaveInstanceState: onSaveInstanceState
(TestFragment.kt:55)#onSaveInstanceState: onSaveInstanceState
(TestStateAFragment.kt:55)#onSaveInstanceState: onSaveInstanceState
(TestActivity.kt:54)#onDestroy: onDestroy
(TestStateAFragment.kt:110)#onDestroyView: onDestroyView
(TestStateBFragment.kt:75)#onDestroyView: onDestroyView
(TestFragment.kt:81)#onDestroyView: onDestroyView
(TestStateAFragment.kt:115)#onDestroy: onDestroy
(TestStateBFragment.kt:80)#onDestroy: onDestroy
(TestFragment.kt:86)#onDestroy: onDestroy
2019-09-18 20:30:10.503 31473-31473/com.example.lifecycleviewmodel W/ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy@d382041
(TestFragment.kt:17)#onAttach: onAttach
(TestFragment.kt:18)#onAttach: TestFragment{544b1c5 (625e084e-68d8-46d6-9527-dfe2694fa5c1) id=0x7f07004c}
(TestFragment.kt:23)#onCreate: onCreate
(TestStateAFragment.kt:30)#onAttach: onAttach
(TestStateAFragment.kt:31)#onAttach: TestStateAFragment{ea5f827 (f73d9a4a-4fb0-4e1c-b6b0-220941525ae2) id=0x7f07004d}
(TestStateAFragment.kt:39)#onCreate: onCreate
(TestStateAFragment.kt:44)#onCreate: com.example.lifecycleviewmodel.fragment.states.a.TestStateAViewModel@fa43f72
(TestStateBFragment.kt:27)#onAttach: onAttach
(TestStateBFragment.kt:28)#onAttach: TestStateBFragment{f66bb79 (a5fa2bce-9b3b-4474-ae2a-0a891f289f65) id=0x7f07004e}
(TestStateBFragment.kt:33)#onCreate: onCreate
(TestActivity.kt:34)#onStart: onStart
(TestFragment.kt:34)#onCreateView: onCreateView
(TestFragment.kt:40)#onViewCreated: onViewCreated
(TestStateAFragment.kt:67)#onCreateView: onCreateView
(TestStateAFragment.kt:73)#onViewCreated: onViewCreated
(TestStateBFragment.kt:44)#onCreateView: onCreateView
(TestStateBFragment.kt:50)#onViewCreated: onViewCreated
(TestFragment.kt:61)#onStart: onStart
(TestStateAFragment.kt:90)#onStart: onStart
(TestStateBFragment.kt:55)#onStart: onStart
(TestActivity.kt:40)#onResume: onResume
(TestFragment.kt:66)#onResume: onResume
(TestStateAFragment.kt:95)#onResume: onResume
(TestStateBFragment.kt:60)#onResume: onResume

那么,这两种情况在哪里完全不同,有没有办法确定发生了哪种情况?

2 个答案:

答案 0 :(得分:1)

发生配置更改时,Android框架将在您的onRetainNonConfigurationInstance()上调用Activity。您可以返回任何想要的对象。然后,Android将销毁您的Activity并立即创建一个新实例。在新实例的onCreate()中,您可以调用getLastNonConfigurationInstance()。如果由于配置更改而重新创建了Activity,则从onRetainNonConfigurationInstance()返回的对象将在此处返回。否则,呼叫返回null。在这种情况下,您可以知道由于配置更改而重新创建Activity的时间,以及由于其他原因重新启动它的时间。

开发者选项“不要保留活动”通常不需要处理,因为普通用户永远不要启用它。您可以将其用于测试目的,以确保Activity可以正确恢复,以防万一Android决定杀死它。

实际上,Android通常不会终止个人活动。如果Android需要从后台应用程序中恢复资源,它通常只会终止整个操作系统过程。但是,我最近发现某些情况下,某些设备确实在后台运行Android时确实杀死了个人活动。当用户返回到应用程序时,Android将重新创建Activity。在这种情况下,您将从null返回getLastNonConfigurationInstance(),但是在Bundle调用中将获得非空onCreate(),并且还将获得非空{ Bundle中的{1}}。因此,您应该能够分辨出以下两者之间的区别:

  • onRestoreInstanceState()首次创建
  • 配置更改后创建的
  • Activity实例
  • Activity实例在Android将其杀死并用户返回后重新创建

请参见https://developer.android.com/reference/android/app/Activity.html?hl=en#onRetainNonConfigurationInstance()

我不确定您的要求,但是此信息应该会有所帮助。

答案 1 :(得分:0)

由于FragmentActivity在consulNode1期间存储了它,因此ViewModel可以保留配置更改,而在Activity的配置更改过程中会调用它。我认为当“不保留活动”模式打开时,或者当Android系统回收Activity时,它不属于配置更改的过程。因此,consulNode2将不会被调用,并且在重新创建Activity之后,ViewModel将无法生存。