ViewModel 源码分析

187 阅读5分钟

1.ViewModel优点

  1. ViewModel类旨在以注重生命周期的方式存储和管理界面相关数据。
  2. ViewModel 类让数据可在发生屏幕旋转等配置更改后继续留存。只有当Activity真正销毁才会执行getViewModelStore().clear(),清除所有的ViewModel。
  3. onSaveInstanceState()只适合序列化和反序列化的少量数据。
  4. viewModelScope为每个ViewModel定义协程作用域,当ViewModel销毁时,协程也跟着销毁。

2.ViewModelProvider(this)创建viewmodel

val vm = ViewModelProvider(this)[ViewModelTest::class.java]
val vm by viewModels<VmTestModel>()
    

简述 by 属性委托 给 Lazy getValue

viewModels: ComponentActivity扩展方法,返回Lazy, Lazy.getValue()扩展方法,返回value ViewModelLazy:Lazy 重写value方法。


public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
          //从当前owner中获取viewmodelStore 
        this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
                ? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
                : NewInstanceFactory.getInstance());
    }

我们都知道ViewModel构造函数传递参数,必须使用Factory创建ViewModel

新版本依赖已经给viewmodel的Factory创建做了解耦,可以改用viewModelFactory{}无状态化构造ViewModel。感兴趣的可自行参阅

"androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1"

ViewModelProvider(this)默认执行的Factory 为 AndroidViewModelFactory

SavedStateViewModelFactory.kt

@SuppressLint("LambdaLast")
    public SavedStateViewModelFactory(@Nullable Application application,
            @NonNull SavedStateRegistryOwner owner,
            @Nullable Bundle defaultArgs) {
        mSavedStateRegistry = owner.getSavedStateRegistry();
        mLifecycle = owner.getLifecycle();
        mDefaultArgs = defaultArgs;
        mApplication = application;
        mFactory = application != null
                ? ViewModelProvider.AndroidViewModelFactory.getInstance(application)
                : ViewModelProvider.NewInstanceFactory.getInstance();
    }

get(VM:class.java) 创建和保存

@NonNull
    @MainThread
    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);
        }
        //保存在 ViewModelStore的HashMap里
        mViewModelStore.put(key, viewModel);
        return (T) viewModel;
    }

AndroidViewModelFactory.create()

反射创建ViewModel对象

        @NonNull
        @Override
        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
            if (AndroidViewModel.class.isAssignableFrom(modelClass)) {
                //noinspection TryWithIdenticalCatches
                try {
                    //反射创建ViewModel对象
                    return modelClass.getConstructor(Application.class).newInstance(mApplication);
                } catch (NoSuchMethodException e) {
                 
            }
            return super.create(modelClass);
        }

3.ViewModel 保存和销毁

VieModelProvider(this)[ViewModelTest::class.java]。

ViewModelStore.kt

mMap储存当前Activity所有的Viewmodel

public class ViewModelStore {

    private final HashMap<String, ViewModel> mMap = new HashMap<>();
    //保存viewmodel
    final void put(String key, ViewModel viewModel) {
        ViewModel oldViewModel = mMap.put(key, viewModel);
        if (oldViewModel != null) {
            oldViewModel.onCleared();
        }
    }
    //获取ViewModel实例
    final ViewModel get(String key) {
        return mMap.get(key);
    }

    Set<String> keys() {
        return new HashSet<>(mMap.keySet());
    }

    //通知每个Viewmodel不可用,并清楚所有的ViewModel
    public final void clear() {
        for (ViewModel vm : mMap.values()) {
            vm.clear();
        }
        mMap.clear();
    }
}

getViewModelStore()

//实现ViewModelStoreOwner 重写getViewModelStore()
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
        ContextAware,
        LifecycleOwner,
        ViewModelStoreOwner,
        HasDefaultViewModelProviderFactory,
        SavedStateRegistryOwner,
        OnBackPressedDispatcherOwner,
        ActivityResultRegistryOwner,
        ActivityResultCaller {
          
        //获取viemodelStore
       @NonNull
       @Override
      public ViewModelStore getViewModelStore() {
        ...
        ensureViewModelStore();
        return mViewModelStore;
    }
 }
  //viewModelStore 初始化
 void ensureViewModelStore() {
        if (mViewModelStore == null) {
            //先从最后一次保存的配置里获取
            NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
            if (nc != null) {
                //尝试恢复
                mViewModelStore = nc.viewModelStore;
            }
            //没有获取到直接创建新的
            if (mViewModelStore == null) {
                mViewModelStore = new ViewModelStore();
            }
        }
    }


@SuppressWarnings("WeakerAccess")
public interface ViewModelStoreOwner {
    
    @NonNull
    ViewModelStore getViewModelStore();
}

onRetainNonConfigurationInstance()

当手机配置发生改变(旋转屏幕)Activity 会销毁,重走onCreate, 但是在onDestory之前执行保存操作

public final Object onRetainNonConfigurationInstance() {
        // Maintain backward compatibility.
        Object custom = onRetainCustomNonConfigurationInstance();
        //获取当前的viewmodelStore
        ViewModelStore viewModelStore = mViewModelStore;
        if (viewModelStore == null) {
            //如果为空,配置中读取
            NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
            if (nc != null) {
                viewModelStore = nc.viewModelStore;
            }
        }
        //没有获取到,直接返回
        if (viewModelStore == null && custom == null) {
            return null;
        }
        //创建 instances实例保存 VewModelStore
        NonConfigurationInstances nci = new NonConfigurationInstances();
        nci.custom = custom;
        nci.viewModelStore = viewModelStore;
        return nci;
    }
    

NonConfigurationInstances(viewmodelStore) 的保存

static final class NonConfigurationInstances {
        Object custom;
        ViewModelStore viewModelStore;
    }

viewmodelStore 状态恢复

 public ComponentActivity() {
        Lifecycle lifecycle = getLifecycle();
        //清除viewmodelStore里的viewmodel
        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();
                    // 清除所有viewmodel
                    if (!isChangingConfigurations()) {
                        getViewModelStore().clear();
                    }
                }
            }
        });
        //当执行onCreate 时候恢复数据
        getLifecycle().addObserver(new LifecycleEventObserver() {
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source,
                    @NonNull Lifecycle.Event event) {
                //从配置从恢复
                ensureViewModelStore();
                //移除Observer
                getLifecycle().removeObserver(this);
            }
        });

       
    }

4.配置改变ViewModel保存在什么地方的?

onRetainNonConfigurationInstace,getLastNonConfigurationInstance()怎么保存和恢复的呢

1.handleDestroyActivity()

当activity销毁时,ActivityThread 执行 handleDestroyActivity
@Override
    public void handleDestroyActivity(ActivityClientRecord r, boolean finishing, int configChanges,
            boolean getNonConfigInstance, String reason) {
        performDestroyActivity(r, finishing, configChanges, getNonConfigInstance, reason);
    }
  
    void performDestroyActivity(ActivityClientRecord r, boolean finishing,
            int configChanges, boolean getNonConfigInstance, String reason) {
       ...
        //如果是配置发生改变
        if (getNonConfigInstance) {
            //把 retainNonConfigurationInstances的值复制给ActivityClientRecord的lastNonConfigurationInstances
          r.lastNonConfigurationInstances = 
                r.activity.retainNonConfigurationInstances();
        }
      ...
     

ActivityClientRecord 是保存在ActivityThread.java下的mActivities中

 final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
    

activity.retainNonConfigurationInstances()

retainNonConfigurationInstances()

NonConfigurationInstances retainNonConfigurationInstances() {
        //调用onRetainNonConfiguration()
        //获取当前保存的viewmodelStore的NonConfigurationInstance实列
        Object activity = onRetainNonConfigurationInstance();
       =...
          //activity 保存在 NonConfigurationInstances
        NonConfigurationInstances nci = new NonConfigurationInstances();
        nci.activity = activity;
        ...
        return nci;
    }
  

NonConfigurationInstances

static final class NonConfigurationInstances {
        Object activity;
        HashMap<String, Object> children;
        FragmentManagerNonConfig fragments;
        ArrayMap<String, LoaderManager> loaders;
        VoiceInteractor voiceInteractor;
    }

执行完onDestory 对象已经保存在 r.lastNonConfigurationInstances

2.handleLaunchActivity

attach()

 final Activity a = performLaunchActivity(r, customIntent);
 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ....
    activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback,
                        r.assistToken, r.shareableActivityToken);
  ....

}

将保存的对象赋值给Activity的 成员变量 mLastNonConfigurationInstances

@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    final void attach(Context context
            ...
            NonConfigurationInstances lastNonConfigurationInstances,
           ...
    ) {
          ...
        ///赋值给mLastNonConfigurationInstances
        mLastNonConfigurationInstances = lastNonConfigurationInstances;

getLastNonConfigurationInstance()

getLastNonConfigurationInstance 获取的就是mLastNonConfigurationInstance的值

  @Nullable
    public Object getLastNonConfigurationInstance() {
        return mLastNonConfigurationInstances != null
                ? mLastNonConfigurationInstances.activity : null;
    }

5.总结

当Activity 销毁时,viewModelStore 通过 onRetainNonConfigurationInstance()
装箱到NonConfigurationInstances对象里,并储存到ActivityClientRecord(简称r)实列里,
而r又存储在ActivityThread的成员变量mActivities里,当Activity重建时,
从r对象中获取NonConfigurationInstances并存储到Activity的成员变量mLastNonConfigurationInstances,
当activity执行oncreate时,从mLastNonConfigurationInstances.viewmodelStore恢复viewmodelStore,
所以从viewmodelStore中获取的Viewmodel是同一对象。

5. 屏幕旋转事件

1.ActivityManagerService.updateConfiguration

@Override
    public boolean updateConfiguration(Configuration values) {
        return mActivityTaskManager.updateConfiguration(values);
    }

2.ActivityTaskManagerService

    @Override
    public boolean updateConfiguration(Configuration values) {
      ...
    updateConfigurationLocked(values, null, false, false /* persistent */,
                        UserHandle.USER_NULL, false /* deferResume */,
                        mTmpUpdateConfigurationResult);
      ...
    }

    boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
            boolean initLocale, boolean persistent, int userId, boolean deferResume,
            ActivityTaskManagerService.UpdateConfigurationResult result) {
            ...
            if (!deferResume) {
                kept = ensureConfigAndVisibilityAfterUpdate(starting, changes);
            }
            ...
        
        return kept;
    }


ensureConfigAndVisibilityAfterUpdate() -> relaunchActivityLocked(preserveWindow);

3.relaunchActivityLocked

try {
        
            final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults,
                    pendingNewIntents, configChangeFlags,
                    new MergedConfiguration(getProcessGlobalConfiguration(),
                            getMergedOverrideConfiguration()),
                    preserveWindow);
            final ActivityLifecycleItem lifecycleItem;
            if (andResume) {
                lifecycleItem = ResumeActivityItem.obtain(isTransitionForward());
            } else {
                lifecycleItem = PauseActivityItem.obtain();
            }
            final ClientTransaction transaction = ClientTransaction.obtain(app.getThread(), appToken);
            transaction.addCallback(callbackItem);
            transaction.setLifecycleStateRequest(lifecycleItem);
            mAtmService.getLifecycleManager().scheduleTransaction(transaction);

执行ActivityRelaunchItem

@Override
    public void execute(ClientTransactionHandler client, ActivityClientRecord r,
            PendingTransactionActions pendingActions) {
        if (mActivityClientRecord == null) {
            if (DEBUG_ORDER) Slog.d(TAG, "Activity relaunch cancelled");
            return;
        }
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
        client.handleRelaunchActivity(mActivityClientRecord, pendingActions);
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    }

4.ActivityThread.handleRelaunchActivity()

    @Override
    public void handleRelaunchActivity(ActivityClientRecord tmp,
            PendingTransactionActions pendingActions) {
          
        handleRelaunchActivityInner(r, configChanges, tmp.pendingResults, tmp.pendingIntents,
                pendingActions, tmp.startsNotResumed, tmp.overrideConfig, "handleRelaunchActivity");
  }

handleRelaunchActivityInner

private void handleRelaunchActivityInner(ActivityClientRecord r, int configChanges,
            List<ResultInfo> pendingResults, List<ReferrerIntent> pendingIntents,
            PendingTransactionActions pendingActions, boolean startsNotResumed,
            Configuration overrideConfig, String reason) {
        // Preserve last used intent, it may be set from Activity#setIntent().
        final Intent customIntent = r.activity.mIntent;
        // Need to ensure state is saved.
        if (!r.paused) {
            //执行onPause
            performPauseActivity(r, false, reason, null /* pendingActions */);
        }
        if (!r.stopped) {
          // onStop
            callActivityOnStop(r, true /* saveState */, reason);
        }
    
        //onDestory 也是在这里保存调用onRetainNonConfigurationInstance 来保存状态的
        handleDestroyActivity(r, false, configChanges, true, reason);

        r.activity = null;
        r.window = null;
        r.hideForNow = false;
        r.nextIdle = null;
        // Merge any pending results and pending intents; don't just replace them
        if (pendingResults != null) {
            if (r.pendingResults == null) {
                r.pendingResults = pendingResults;
            } else {
                r.pendingResults.addAll(pendingResults);
            }
        }
        if (pendingIntents != null) {
            if (r.pendingIntents == null) {
                r.pendingIntents = pendingIntents;
            } else {
                r.pendingIntents.addAll(pendingIntents);
            }
        }
        r.startsNotResumed = startsNotResumed;
        r.overrideConfig = overrideConfig;
    
        //重新执行 , getLastNonConfigurationInstance 的 attach 完成赋值
        handleLaunchActivity(r, pendingActions, customIntent);
    }