android - "Don' t keep activities”和配置更改有什么区别?

标签 android android-lifecycle android-viewmodel

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

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

以下日志来 self 尝试过的示例项目。这有一个 Activity TestActivity,其中包含一个 fragment TestFragment,而 TestFragment 包含两个 fragment 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

不要停止 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 终止并用户返回后重新创建

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

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

关于android - "Don' t keep activities”和配置更改有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57996041/

相关文章:

Android 模拟器皮肤布局 - 是否有工具和规范?

android - 空对象引用上 android.view.View android.view.View.findViewById(int) 的 onCreateOptionsMenu 问题

android - 在不同的过程中打开相机

java - ViewModel 没有零参数构造函数错误,原因是 ViewModelFactory 一直为 null(不是 100% 确定)

java - arrayList 似乎仅在先完成一个 Activity (而不是另一个 Activity )时才会创建

android - Android Application.getInstance 是否一直存在?

android - 使用 Room 实时查询进行生命周期状态管理

android - 这是 LiveData 的正确使用方式吗?

android - 在数据源分页中更改 listId/query 的更好方法

android - Android中公共(public)静态变量的生命周期