我正在使用 View 模型架构组件来处理 UI 状态并包含业务逻辑。众所周知,它在配置更改后仍然存在,但是当在开发人员选项中打开“不保留 Activity ”选项时,将创建一个新的 View 模型实例。在这两种情况下都会调用 onDestroy Activity ,那么两者之间有什么区别?
我在 View Model 中维护一个状态机并在恢复它时面临问题,因为 View Model 无法生存。我不能使用实例状态,因为它有复杂的对象。
以下日志来 self 尝试过的示例项目。这有一个 Activity TestActivity
,其中包含一个 fragment TestFragment
,而 TestFragment
包含两个 fragment TestStateAFragment
和 TestStateBFragment
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
不要停止 Activity :
(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
不要让 Activity 保持开启状态:
(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 ”不是您通常需要处理的事情,因为普通用户永远不应该启用它。您可以将它用于测试目的,以确保您的 Activity
在 Android 决定终止它的情况下正确恢复。
实际上,Android 通常不会终止个别 Activity 。如果 Android 需要从后台应用程序中恢复资源,它通常会终止整个操作系统进程。但是,我最近在某些设备上看到了一些情况,当应用程序处于后台时,Android 确实会终止个别 Activity 。当用户随后返回应用程序时,Android 将重新创建 Activity
。在这种情况下,您将从 getLastNonConfigurationInstance()
返回 null
,但您会在 onCreate( )
调用,您还将在 onRestoreInstanceState()
中获得一个非空的 Bundle
。所以你应该能够区分:
Activity
第一次创建Activity
配置更改后创建的实例Activity
实例在 Android 终止并用户返回后重新创建
我不太确定您的要求,但这些信息应该有所帮助。
关于android - "Don' t keep activities”和配置更改有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57996041/