繁体   English   中英

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

[英]What is the difference between "Don't keep activities" and a Configuration change?

我正在使用视图模型架构组件来处理 UI 状态并包含业务逻辑。 众所周知,它在配置更改后仍然存在,但是当“开发人员”选项中的“不保留活动”选项打开时,会创建一个新的视图模型实例。 在这两种情况下都调用了 onDestroy 活动,那么两者之间有什么区别?

我在视图模型中维护一个状态机,并在恢复它时面临问题,因为视图模型无法生存。 我不能使用实例状态,因为它有复杂的对象。

以下日志来自我尝试过的示例项目。 这有一个包含片段TestFragment的 Activity TestActivity ,并且TestFragment包含两个片段TestStateAFragmentTestStateBFragment

测试活动.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()
    }
}

测试片段.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()
    }
}

测试状态片段.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

那么这两种情况究竟有何不同,有没有办法确定发生了哪一种情况?

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

开发人员选项“不要保留活动”不是您通常必须处理的事情,因为普通用户永远不应该启用它。 您可以将其用于测试目的,以确保您的Activity能够在 Android 决定将其关闭时正确恢复。

实际上,Android 通常不会终止个人活动。 如果 Android 需要从后台应用程序中恢复资源,它通常只会终止整个操作系统进程 但是,我最近在某些设备上看到了一些情况,当应用程序在后台时,Android 确实会终止个别活动。 当用户返回应用程序时,Android 将重新创建Activity 在这种情况下,你会得到null从返回getLastNonConfigurationInstance()但你会得到一个非空BundleonCreate()调用,你也将获得一个非空BundleonRestoreInstanceState() 所以你应该能够分辨出以下之间的区别:

  • 首次创建的Activity
  • 配置更改后创建的Activity实例
  • Activity实例在 Android 将其关闭且用户返回后重新创建

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM