什么时候调用视图模型 onCleared

When is the viewmodel onCleared called

ViewModel 是否独立于 activity/fragment 生命周期或仅依赖于它们的配置更改。它们何时不复存在并调用后续的 onCleared() 方法。 viewModel 可以与另一个 Activity 共享吗?

一个情况:

Activity1+viewModel1--->(rotation)--->Activity1+viewModel1
--->(launch Intent)--->Activity2+viewModel1

这种共享是否可行,是否是一种好的做法。

此外,由于应用程序生命周期回调,onPause->onStop->onDestroy 对两者都是相同的

1.activity旋转和

2.when一个Activity结束,

ViewModel 如何在内部确定调用 onCleared 并最终结束其生命周期的正确时间。


调查结果

ViewModel 在内部使用 holderFragment 来保存 activity 的实例,并像片段一样使用 setRetainInstance 方法来处理配置更改。

Source: dive-inside-of-androids-viewmodel-architecture-components

Are ViewModels independent of activity/fragment lifecycles or just their configuration changes.

ViewModels (VM) 独立于配置更改,并在 activity/fragment 被销毁时被清除。

以下是来自官方网站的lifecycle of ViewModel

Can the viewModel be shared with another Activity ?

您不应该对活动执行此操作。但是片段可以共享一个 ViewModel 使用它们的 activity 作用域来处理它们之间的通信

How is a ViewModel figuring out internally the right time to call onCleared and finally end its lifecycle?

当应用程序进入后台并终止应用程序进程以释放系统内存时,将调用 VM onCleared

Do ViewModels persist my data? section from this Android Developer's post, ViewModels: Persistence, onSaveInstanceState(), Restoring UI State and Loaders

如果您希望用户能够将应用程序置于后台,然后在三个小时后返回到完全相同的状态,您还应该持久化数据。这是因为一旦您的 activity 进入后台,如果设备 运行 内存不足,您的应用程序进程可能会停止。

如果应用程序进程和 activity 停止,则 ViewModel 也将被清除。

通过源码我们知道ViewModel绑定了HolderFragment。你可以从classViewModelProviders中的代码中找到它。

@MainThread
public static ViewModelProvider of(@NonNull FragmentActivity activity,
        @NonNull Factory factory) {
    checkApplication(activity);
    return new ViewModelProvider(ViewModelStores.of(activity), factory);
}

接下来,在-class上的HolderFragment是onDestroy()可以找到

@Override
public void onDestroy() {
    super.onDestroy();
    mViewModelStore.clear();
}

最后,打开它,

public final void clear() {
 for (ViewModel vm : mMap.values()) {
        vm.onCleared();
   }
    mMap.clear();
}

现在,也许你已经知道了。就像上面的图片一样。当片段完成时,它被清除; activity 重新创建时,片段的 onDestroy() 不会被调用,因为

public HolderFragment() {
    setRetainInstance(true);
}

希望对您有所帮助

Fragment.java

中检查方法onDestroy()
public void onDestroy() {
     this.mCalled = true;
     FragmentActivity activity = this.getActivity();
     boolean isChangingConfigurations = activity != null && activity.isChangingConfigurations();
     if (this.mViewModelStore != null && !isChangingConfigurations) {
         this.mViewModelStore.clear();
     }
}

变量isChangingConfigurations在Activity旋转时为真,viewModelStore方法clear() 未被调用。

当Activity被销毁时,isChangingConfigurations为false,viewModelStore会被清除

如果你跟踪(检查超级class) AppCompatActivity --> FragmentActivity --> ComponentActivity

ComponentActivity 观察生命周期状态。

onDestory() 在配置更改(例如屏幕旋转)时调用,但由于以下情况,viewModel 未被销毁。

getLifecycle().addObserver(new GenericLifecycleObserver() {
            @Override
            public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
                if (event == Lifecycle.Event.ON_DESTROY) {
                    if (!isChangingConfigurations()) {
                        getViewModelStore().clear();
                    }
                }
            }
        });

我希望在 Activity 完成时调用 VM 的 onClear。我使用 onPause,因为对 onDestroy 的调用并不总是立即执行...它可能在 onPause:

之后几秒钟
class SomeActivity : AppCompatActivity() {

    override fun onPause() {
        super.onPause()

        // viewmodel is not always cleared immediately after all views detach from it, which delays
        // the vm's cleanup code being called, which lets the resources continue running
        // after all UIs detach, which is weird, because I was using timers and media players.
        // this makes the VM execute onCleared when its Activity detaches from it.
        if (isFinishing) {
            viewModelStore.clear()
        }
    }
}