ViewModel源码分析

知识点

  1. ViewModelProviders:ViewModelProvider的工厂方法。
  2. ViewModelProvider:工具类,通过反射的方式创建ViewModel。
  3. AndroidViewModelFactory:ViewModelProvider的静态内部类 ,全局单例只有一个 ,用于实现反射创建ViewModel。
  4. ViewModelStores:ViewModelStore的工厂方法类。
  5. ViewModelStore:使用HashMap存储ViewModel,key为:“DEFAULT_KEY + ":" + canonicalName”。
  6. HolderFragment:系统为你的Activity添加一个具有提供ViewModelStore的Fragment,并且因为这个Fragment调用了setRetainInstance(true),所以它能够跨越activity的生命周期。

使用

ViewModelProviders.of(getActivity()).get(MainViewModel.class);

类图

viewmodel_类图

时序图

viewmodel_时序图

分析

创建ViewModelProvider

@NonNull
@MainThread
public static ViewModelProvider of(@NonNull FragmentActivity activity) {
    return of(activity, null);
}

@NonNull
@MainThread
public static ViewModelProvider of(@NonNull FragmentActivity activity,
        @Nullable Factory factory) {
    Application application = checkApplication(activity);
    if (factory == null) {
        //创建工厂类,用于反射创建ViewModel
        factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
    }
    //创建ViewModelProvider
    return new ViewModelProvider(ViewModelStores.of(activity), factory);
}

获取ViewModel

@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
    String canonicalName = modelClass.getCanonicalName();
    if (canonicalName == null) {
        throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
    }
    return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}

@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
    ViewModel viewModel = mViewModelStore.get(key);
    //当使用不同的类加载器加载同一个类的时候,这里会是 false
    if (modelClass.isInstance(viewModel)) {
        //noinspection unchecked
        return (T) viewModel;
    } else {
        //noinspection StatementWithEmptyBody
        if (viewModel != null) {
            // TODO: log a warning.
        }
    }
    //通过反射创建ViewModel
    viewModel = mFactory.create(modelClass);
    //存储ViewModel到ViewModelStore中
    mViewModelStore.put(key, viewModel);
    //noinspection unchecked
    return (T) viewModel;
}

@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
    if (AndroidViewModel.class.isAssignableFrom(modelClass)) {
        //noinspection TryWithIdenticalCatches
        try {
            return modelClass.getConstructor(Application.class).newInstance(mApplication);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException("Cannot create an instance of " + modelClass, e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Cannot create an instance of " + modelClass, e);
        } catch (InstantiationException e) {
            throw new RuntimeException("Cannot create an instance of " + modelClass, e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException("Cannot create an instance of " + modelClass, e);
        }
    }
    return super.create(modelClass);
}

获取ViewModelStore

@NonNull
@MainThread
public static ViewModelStore of(@NonNull FragmentActivity activity) {
    //我们的activity可以自己实现ViewModelStoreOwner,默认情况下,这里的判断为false,ViewModelStoreOwner由HolderFragment实现
    if (activity instanceof ViewModelStoreOwner) {
        return ((ViewModelStoreOwner) activity).getViewModelStore();
    }
    //holderFragmentFor在HolderFragment中实现
    return holderFragmentFor(activity).getViewModelStore();
}

获取HolderFragment

/**
 * @hide
 */
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public static HolderFragment holderFragmentFor(FragmentActivity activity) {
    return sHolderFragmentManager.holderFragmentFor(activity);
}

HolderFragment holderFragmentFor(FragmentActivity activity) {
    FragmentManager fm = activity.getSupportFragmentManager();
    //通过fragmentManager获取fragment实例
    HolderFragment holder = findHolderFragment(fm);
    if (holder != null) {
        return holder;
    }
    holder = mNotCommittedActivityHolders.get(activity);
    if (holder != null) {
        return holder;
    }

    if (!mActivityCallbacksIsAdded) {
        mActivityCallbacksIsAdded = true;
        activity.getApplication().registerActivityLifecycleCallbacks(mActivityCallbacks);
    }
    holder = createHolderFragment(fm);
    //我们add进去的fragment并不会马上就执行完(也就是说,这个方法执行完成后,马上再调用一次,上面的findHolderFragment会返回 null。但是这没有关系,因为接下来我们还可从mNotCommittedActivityHolders获取到对应的实例),所以我们这里先把他放mNotCommittedActivityHolders中。NotCommitted表示fragment的commit还没有完成
    mNotCommittedActivityHolders.put(activity, holder);
    return holder;
}

private static HolderFragment createHolderFragment(FragmentManager fragmentManager) {
    HolderFragment holder = new HolderFragment();
    //这个fragment只是用来存数据,允许他的状态丢失可以让用户在更多情景下使用我们的API。例如,onStop()中也可以使用(当然,onDestroy就不行了,因为我们需要往activity悄悄添加一个fragment)
    fragmentManager.beginTransaction().add(holder, HOLDER_TAG).commitAllowingStateLoss();
    return holder;
}

public HolderFragment() {
    //如此一来,当activity由于屏幕旋转等被系统销毁时,这个fragment实例也不会被销毁
    setRetainInstance(true);
}

/**
 * Control whether a fragment instance is retained across Activity
 * re-creation (such as from a configuration change).  This can only
 * be used with fragments not in the back stack.  If set, the fragment
 * lifecycle will be slightly different when an activity is recreated:
 * <ul>
 * <li> {@link #onDestroy()} will not be called (but {@link #onDetach()} still
 * will be, because the fragment is being detached from its current activity).
 * <li> {@link #onCreate(Bundle)} will not be called since the fragment
 * is not being re-created.
 * <li> {@link #onAttach(Activity)} and {@link #onActivityCreated(Bundle)} <b>will</b>
 * still be called.
 * </ul>
 */
public void setRetainInstance(boolean retain) {
    mRetainInstance = retain;
}

参考文章

添加新评论