ViewModel#onCleared的实现原理

开局一个问题

请问ViewModel#onCleared的回调和Activity#onDestoryed的生命周期哪个更早?

开始源码分析

我们构建ViewModel, 需要传入Activity或者fragment。都会走到下面的方法, get的时候也是从ViewModelStore 去拿和获取

less 复制代码
 public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
        mFactory = factory;
        mViewModelStore = store;
 }
 
  public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
        ViewModel viewModel = mViewModelStore.get(key);

        if (modelClass.isInstance(viewModel)) {
            if (mFactory instanceof OnRequeryFactory) {
                ((OnRequeryFactory) mFactory).onRequery(viewModel);
            }
            return (T) viewModel;
        } else {
            //noinspection StatementWithEmptyBody
            if (viewModel != null) {
                // TODO: log a warning.
            }
        }
        if (mFactory instanceof KeyedFactory) {
            viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
        } else {
            viewModel = mFactory.create(modelClass);
        }
        mViewModelStore.put(key, viewModel);
        return (T) viewModel;
    }

所以从ViewModel的构建,我们知道是ViewModelStore进行维护了ViewModel的生命周期

ViewModelStore的管理

ViewModelStore的管理,需要实现ViewModelStoreOwner 接口,我们代码中主要 ComponentActivityFragment 实现了该接口,这里源码分析以ComponentActivity 分析

less 复制代码
 public ComponentActivity() {
    //...
    getLifecycle().addObserver(new LifecycleEventObserver() {
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source,
                    @NonNull Lifecycle.Event event) {
                if (event == Lifecycle.Event.ON_DESTROY) {
                    // Clear out the available context
                    mContextAwareHelper.clearAvailableContext();
                    // And clear the ViewModelStore
                    if (!isChangingConfigurations()) {
                        getViewModelStore().clear();
                    }
                }
            }
        });
    //...
 }

ComponentActivity 的构造方法的时候,我们发现Activty#getViewModelStore 会在lifecycleOwner#on_Destory的时候调用 clear方法,进入调用ViewModel#onClear方法,完成ViewModel的清理(tips: 这里有如果是配置变化引起的Activty的重建,并不会调用clear方法)

所以这个问题变成了Lifecycle#on_destory 事件回调和Activty#onDestory的时机问题

Lifecycle#on_destory 回调时机?

lifecycle的onEvent 主要是LifecycleRegistry

less 复制代码
public class LifecycleRegistry extends Lifecycle {

      public void setCurrentState(@NonNull State state) {
        enforceMainThreadIfNeeded("setCurrentState");
        moveToState(state);
      }

      public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
        enforceMainThreadIfNeeded("handleLifecycleEvent");
        moveToState(event.getTargetState()); //这个地方去回调所有的Observer
    }
}

我在外面查了半天,外面查了半天,都没有找到 setCurrentStatehandleLifecycleEvent 调用的地方。直到我看到这个代码

less 复制代码
 @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        ...
        ReportFragment.injectIfNeededIn(this);
        ....
    }
scss 复制代码
public class ReportFragment extends android.app.Fragment {
    private static final String REPORT_FRAGMENT_TAG = "androidx.lifecycle"
            + ".LifecycleDispatcher.report_fragment_tag";

    public static void injectIfNeededIn(Activity activity) {
        if (Build.VERSION.SDK_INT >= 29) {
            // On API 29+, we can register for the correct Lifecycle callbacks directly
            LifecycleCallbacks.registerIn(activity);
        }
        // Prior to API 29 and to maintain compatibility with older versions of
        // ProcessLifecycleOwner (which may not be updated when lifecycle-runtime is updated and
        // need to support activities that don't extend from FragmentActivity from support lib),
        // use a framework fragment to get the correct timing of Lifecycle events
        android.app.FragmentManager manager = activity.getFragmentManager();
        if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
            manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
            // Hopefully, we are the first to make a transaction.
            manager.executePendingTransactions();
        }
    }

    @SuppressWarnings("deprecation")
    static void dispatch(@NonNull Activity activity, @NonNull Lifecycle.Event event) {
        if (activity instanceof LifecycleRegistryOwner) {
            ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
            return;
        }

        if (activity instanceof LifecycleOwner) {
            Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
            if (lifecycle instanceof LifecycleRegistry) {
                 //此处进行分发的
                ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
            }
        }
    }

    static ReportFragment get(Activity activity) {
        return (ReportFragment) activity.getFragmentManager().findFragmentByTag(
                REPORT_FRAGMENT_TAG);
    }

    private ActivityInitializationListener mProcessListener;

    private void dispatchCreate(ActivityInitializationListener listener) {
        if (listener != null) {
            listener.onCreate();
        }
    }

    private void dispatchStart(ActivityInitializationListener listener) {
        if (listener != null) {
            listener.onStart();
        }
    }

    private void dispatchResume(ActivityInitializationListener listener) {
        if (listener != null) {
            listener.onResume();
        }
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        dispatchCreate(mProcessListener);
        dispatch(Lifecycle.Event.ON_CREATE);
    }

    @Override
    public void onStart() {
        super.onStart();
        dispatchStart(mProcessListener);
        dispatch(Lifecycle.Event.ON_START);
    }

    @Override
    public void onResume() {
        super.onResume();
        dispatchResume(mProcessListener);
        dispatch(Lifecycle.Event.ON_RESUME);
    }

    @Override
    public void onPause() {
        super.onPause();
        dispatch(Lifecycle.Event.ON_PAUSE);
    }

    @Override
    public void onStop() {
        super.onStop();
        dispatch(Lifecycle.Event.ON_STOP);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        dispatch(Lifecycle.Event.ON_DESTROY);
        // just want to be sure that we won't leak reference to an activity
        mProcessListener = null;
    }
}

利用了 Fragment 的生命周期回调,去监听 Activity 的生命周期,从而把生命周期事件(onStart/onStop/onResume...)转发给 Lifecycle → LiveData → LifecycleObserver。

这样好处:

  • 关注点分离:Activity 专注于业务逻辑,生命周期管理交给专门组件
  • 可测试性:Lifecycle 逻辑可以独立测试
  • 一致性:所有 Activity 都有统一的生命周期管理方式

好的,这个问题就变成了Fragment#onDestory 和 Activity#onDestory的生命周期的问题

Fragment#onDestory的回调

Activity 中的 Fragment的生命周期回调,是受 FragmentController 控制的,我们可以看到这个代码performDestroy

scss 复制代码
final void performDestroy() {
        dispatchActivityPreDestroyed();
        mDestroyed = true;
        mWindow.destroy();
        mFragments.dispatchDestroy(); //Fragment 执行onDestory方法
        onDestroy(); //activity的 onDestroy方法
        EventLogTags.writeWmOnDestroyCalled(mIdent, getComponentName().getClassName(),
                "performDestroy");
        mFragments.doLoaderDestroy();
        if (mVoiceInteractor != null) {
            mVoiceInteractor.detachActivity();
        }
        dispatchActivityPostDestroyed();
    }

从这里可以得出问题结论,fragment#onDestroy 会在 Activity#onDestroy方法之前执行

Activity#performDestroy

activity#performDestroy 是哪里调过来的,其实我们知道activity的生命周期都是AMS跨进程调用ApplicationThread, 然后 ApplicationThread 通过H handler 执行 activity的生命周期方法。 所以我们应该可以从ActivityThread类中找到对应的代码。 下面贴出对应的代码作证一下

arduino 复制代码
class H extends Handler{
   ....
   case EXECUTE_TRANSACTION:
        final ClientTransaction transaction = (ClientTransaction) msg.obj;
        mTransactionExecutor.execute(transaction);
   ...
       break;

}

class TransactionExecutor{
   ...
    private void performLifecycleSequence(ActivityClientRecord r, IntArray path,
            ClientTransaction transaction) {
            ....
                case ON_DESTROY:
                    mTransactionHandler.handleDestroyActivity(r.token, false /* finishing */,
                            0 /* configChanges */, false /* getNonConfigInstance */,
                            "performLifecycleSequence. cycling to:" + path.get(size - 1));
                    break;
              ...
            }
        }
}

class ActivityThread{
     public void handleDestroyActivity(IBinder token, boolean finishing, int configChanges,
            boolean getNonConfigInstance, String reason) {
            ....
            mInstrumentation.callActivityOnDestroy(r.activity);
      }
}

class Instrumentation{
    public void callActivityOnDestroy(Activity activity) {
      activity.performDestroy(); //真正调用地方
  }
}

总结整理一下

  1. AMS 发送 Activity#onDestroy → ApplicationThread →ActivityThread
  2. Activity#performDestroy()
  3. performDestroy 方法中,先让Fragment执行onDestroy, 然后执行自己的onDestroy方法
  4. Activity的lifecycle 的 Event的事件实现原理是,依赖Fragment的onDestroy声明周期
  5. ViewModelStore 接收到Actvity#lifecycle#onDestroy 调用ViewModel的cleared 方法

上面问题答案呼之欲出: ViewModel的cleared 是先于 Activity#onDestroy

相关推荐
CheungChunChiu1 小时前
Android 系统中的 NTP 服务器配置与选择逻辑详解
android·运维·服务器
q***49861 小时前
MySQL数据的增删改查(一)
android·javascript·mysql
aqi001 小时前
FFmpeg开发笔记(九十一)基于Kotlin的Android直播开源框架RootEncoder
android·ffmpeg·kotlin·音视频·直播·流媒体
鹏多多2 小时前
flutter睡眠与冥想数据可视化神器:sleep_stage_chart插件全解析
android·前端·flutter
勇气要爆发2 小时前
【第五阶段-高级特性和架构】第三章:高级状态管理—GetX状态管理篇
android·架构
未来之窗软件服务5 小时前
服务器运维(十五)自建WEB服务C#PHP——东方仙盟炼气期
android·服务器运维·东方仙盟·东方仙盟sdk·自建web服务
Zender Han9 小时前
Flutter 新版 Google Sign-In 插件完整解析(含示例讲解)
android·flutter·ios·web
来来走走12 小时前
Android开发(Kotlin) LiveData的基本了解
android·开发语言·kotlin
。puppy13 小时前
MySQL 远程登录实验:通过 IP 地址跨机器连接实战指南
android·adb