Android JetPack ViewModel源码分析

本文从本人的《一文搞懂Android JetPack组件原理之Lifecycle、LiveData、ViewModel与源码分析技巧》拆分而来,主要采用逐类源码分析方法探寻ViewModel的原理,原文内容更加全面,欢迎收藏。

组件介绍

ViewModel是MVVM中的VM,被设计用来管理View依赖的数据,通常是持有LiveData和相关的处理逻辑。ViewModel管理的数据有一个特点,就是不会随着页面配置改变而销毁,但在页面销毁时则会正常跟着销毁。

下面的例子中,自定义了一个ViewModel,管理users这组数据,并且封装了加载users的处理逻辑。而View只需要监听users,在回调中根据users处理界面就好,这样就做到了界面和数据的分离。

public class MyViewModel extends ViewModel {
    private MutableLiveData<List<User>> users;
    public LiveData<List<User>> getUsers() {
        if (users == null) {
            users = new MutableLiveData<List<User>>();
            loadUsers();
        }
        return users;
    }

    private void loadUsers() {
        // Do an asynchronous operation to fetch users.
    }
}

public class MyActivity extends AppCompatActivity {
    public void onCreate(Bundle savedInstanceState) {
        MyViewModel model = new ViewModelProvider(this).get(MyViewModel.class);
    }
}

逐类分析

逐类分析的方式适合对一个组件不了解的情况下使用,以期快速地掌握大概原理。整个过程就是以总结类功能为目的,对组件的相关类逐个通过跳转方法进入,快速阅读并做出总结,掌握类功能定义,为以后使用其它方式进一步理解源码做好准备。下面以这个方式分析一下ViewModel的源码。

第一部分的例子中定义了一个ViewModel的子类MyViewModel,然后通过ViewModelProvider的实例方法get()获取到MyViewModel的实例。

ViewModelProvider

/**
 * Creates {@code ViewModelProvider}. This will create {@code ViewModels}
 * and retain them in a store of the given {@code ViewModelStoreOwner}.
 * 

* This method will use the * {@link HasDefaultViewModelProviderFactory#getDefaultViewModelProviderFactory() default factory} * if the owner implements {@link HasDefaultViewModelProviderFactory}. Otherwise, a * {@link NewInstanceFactory} will be used. */ public ViewModelProvider(@NonNullViewModelStoreOwner owner) { this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory ?((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory() : NewInstanceFactory.getInstance()); } /** * Creates {@code ViewModelProvider}, which will create {@code ViewModels} via the given * {@code Factory} and retain them in the given {@code store}. * * @param store {@code ViewModelStore} where ViewModels will be stored. * @param factory factory a {@code Factory} which will be used to instantiate * new {@code ViewModels} */ public ViewModelProvider(@NonNullViewModelStore store, @NonNull Factory factory) { mFactory =factory; mViewModelStore =store; }

从构造方法中可以看出ViewModelProvider需要ViewModelStore和Factory两个类型的成员变量才能构造处理,分别是mViewModelStore和mFactory,ComponentActivity和Fragment分别都实现了ViewModelStoreOwner和HasDefaultViewModelProviderFactory接口,所以都可以从中获取到ViewModelStore和Factory的实例。

@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);
}
@MainThread
public <T extends ViewModel> T get(@NonNull String key, @NonNullClass<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;
}

get()方法首先尝试通过mViewModelStore的get()方法获取ViewModel的实例,如果没获取到则使用mFactory的create()创建实例,创建出来后则存入到mViewModelStore中。在这里mFactory就是ViewModel的构造工厂,mViewModelStore则是ViewModel的缓存管理者。

ViewModelProvider作为ViewModel的提供者,使用缓存mViewModelStore和工厂mFactory实现,第一次提供ViewModel时会通过工厂创建出来,后续则都是从缓存中拿。

ViewModelStore

public ComponentActivity() {
        ...
        getLifecycle().addObserver(new LifecycleEventObserver() {
        @Override
        public void onStateChanged(@NonNull LifecycleOwner source,
                                   @NonNull Lifecycle.Event event) {
            if(event == Lifecycle.Event.ON_DESTROY) {
                if (!isChangingConfigurations()) {
                   getViewModelStore().clear();
                }
            }
        }
    });
}
@NonNull
@Override
public ViewModelStore getViewModelStore() {
    if (getApplication() == null) {
        throw new IllegalStateException("Your activity is not yet attached to the "
                                        + "Application instance. You can't request ViewModel before onCreate call.");
    }
    if (mViewModelStore == null) {
        NonConfigurationInstances nc =
            (NonConfigurationInstances) getLastNonConfigurationInstance();
        if (nc!= null) {
            // Restore the ViewModelStore from NonConfigurationInstances
            mViewModelStore = nc.viewModelStore;
        }
        if(mViewModelStore == null) {
            mViewModelStore = new ViewModelStore();
        }
    }
    return mViewModelStore;
}

ViewModelStoreOwner接口getViewModelStore()的实现就是提供一个ViewModelStore实例,而ComponentActivity使用Lifecycle能力在页面销毁时调用ViewModelStore实例的clear方法,清空其中的ViewModel。

public class ViewModelStore {
 
    private final HashMap<String, ViewModel> mMap = new HashMap<>();
 
    final void put(String key, ViewModel viewModel) {
        ViewModel oldViewModel = mMap.put(key, viewModel);
        if(oldViewModel != null) {
            oldViewModel.onCleared();
        }
    }
 
    final ViewModel get(String key) {
        returnmMap.get(key);
    }
 
    Set<String> keys() {
        return new HashSet<>(mMap.keySet());
    }
 
    /**
     *  Clears internal storage and notifies ViewModels that they are no longer used.
     */
    public final void clear() {
        for(ViewModel vm : mMap.values()) {
            vm.clear();
        }
        mMap.clear();
    }
}

ViewModelStore中使用HashMap管理ViewModel缓存,它被页面持有,并在页面真正销毁时才清空缓存。

官网的这张图中可以说明ViewModel的生命周期。Android JetPack ViewModel源码分析_第1张图片

SaveStateViewModelFactory

public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
    if (getApplication() == null) {
        throw new IllegalStateException("Your activity is not yet attached to the "
                                        + "Application instance. You can't request ViewModel before onCreate call.");
    }
    if (mDefaultFactory == null) {
        mDefaultFactory = new SavedStateViewModelFactory(
            getApplication(),
            this,
            getIntent() != null ?getIntent().getExtras() : null);
    }
    return mDefaultFactory;
}

ComponentActivity中getDefaultViewModelProviderFactory()方法通过构造方法创建一个SavedStateViewModelFactory对象,传入了Application、当前ComponentActivity实例和Intent中的数据bundle。

SavedStateViewModelFactory构造方法
public SavedStateViewModelFactory(@NonNull Application application,
                                  @NonNull SavedStateRegistryOwner owner,
                                  @Nullable Bundle defaultArgs) {
    mSavedStateRegistry = owner.getSavedStateRegistry();
    mLifecycle =owner.getLifecycle();
    mDefaultArgs =defaultArgs;
    mApplication =application;
    mFactory =ViewModelProvider.AndroidViewModelFactory.getInstance(application);
}

构造方法接受的参数中,页面实例是SavedStateRegistryOwner接口类型的,通过该接口获取到SavedStateRegistry和Lifecycle。另外成员变量mFactory是AndroidViewModelFactory的单例对象。

SavedStateViewModelFactory的create()
@Override
public <T extends ViewModel> T create(@NonNull String key, @NonNullClass<T> modelClass) {
    boolean isAndroidViewModel= AndroidViewModel.class.isAssignableFrom(modelClass);
    Constructor<T> constructor;
    if(isAndroidViewModel) {
        constructor =findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE);
    } else {
        constructor =findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE);
    }
    // doesn't need SavedStateHandle
    if (constructor == null) {
        returnmFactory.create(modelClass);
    }
 
    SavedStateHandleController controller = SavedStateHandleController.create(
        mSavedStateRegistry, mLifecycle, key, mDefaultArgs);
    try {
        T viewmodel;
        if(isAndroidViewModel) {
            viewmodel =constructor.newInstance(mApplication, controller.getHandle());
        } else {
            viewmodel =constructor.newInstance(controller.getHandle());
        }
       viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller);
        returnviewmodel;
    } catch (IllegalAccessException e) {
        throw new RuntimeException("Failed to access " + modelClass, e);
    } catch(InstantiationException e) {
        throw new RuntimeException("A " + modelClass + " cannot be instantiated.", e);
    } catch(InvocationTargetException e) {
        throw new RuntimeException("An exception happened in constructor of "
                                   + modelClass, e.getCause());
    }
}

create()方法支持创建三种类型的ViewModel:AndroidViewModel、支持SavedState的ViewModel、普通ViewModel,这里由于篇幅原因,只分析一下普通ViewModel的创建。普通ViewModel通过mFactory的create()方法创建出来。

AndroidViewModelFactory的create()
public static class AndroidViewModelFactory extendsViewModelProvider.NewInstanceFactory {
    ...
    @NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
        if(AndroidViewModel.class.isAssignableFrom(modelClass)) {
            //noinspection TryWithIdenticalCatches
            try {
                returnmodelClass.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);
    }
}

AndroidViewModelFactory的create()方法判断如果不是AndroidViewModel类型,就直接通过父类的create()方法创建,而AndroidViewModelFactory的父类是NewInstanceFactory。

NewInstanceFactory的create()
public static class NewInstanceFactory implements Factory {
    ...
 
    @SuppressWarnings("ClassNewInstance")
    @NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
        //noinspection TryWithIdenticalCatches
        try {
            returnmodelClass.newInstance();
        } catch(InstantiationException e) {
            throw new RuntimeException("Cannot create an instance of " + modelClass, e);
        } catch(IllegalAccessException e) {
            throw new RuntimeException("Cannot create an instance of " + modelClass, e);
        }
    }
}

NewInstanceFactory的create()则是直接通过反射创建出ViewModel实例。

SaveStateViewModelFactory作为ComponentActivity和Fragment提供的对象,在NewInstanceFactory的基础上增加了对AndroidViewModel和支持SavedStated的ViewModel的创建,但对于普通的ViewModel创建,最后还是降级使用NewInstanceFactory完成。

到此,ViewModel的主要类已经分析完了,接下来可以结合类关系,一定程度上总结出对全局视角的理解。
Android JetPack ViewModel源码分析_第2张图片

主要类说明

  • ViewModelProvider:ViewModel提供者
  • ViewModelStore:ViewModel缓存管理
  • ViewModelProvider.Factory:ViewModel创建工厂
  • SavedStateViewModelFactory:ViewModel创建工厂的实现
  • NewInstanceFactory:普通ViewModel创建工厂的实现

类关系描述

ViewModel通过ViewModelProvider的get()方法获取到,ViewModelProvider由缓存ViewModelStore和创建工厂ViewModelProvider.Factory组合而成,ViewModelStore和ViewModelProvider.Factory也是ComponentActivity的一部分,ComponentActivity通过实现ViewModelStoreOwner和HasDefaultViewModelProviderFactory两个接口对外提供ViewModelStore和ViewModelProvider.Factory。其中,ViewModelProvider.Factory在ComponentActivity的具体实现是SavedStateViewModelFactory,SavedStateViewModelFactory一部分由AndroidViewModelFactory组合而成,它提供创建三种ViewModel的能力,其中普通ViewModel的创建是由AndroidViewModelFactory的父类NewInstanceFactory完成。

逐类分析方法总结

逐类分析重点在于抓大放小,分析每个类的主要目的是掌握该类的功能定位,达到目的即可,不要深陷到源码细节中。在快速分析完后,结合相关的类做出总结,从而获得整体上的了解,为以后进一步源码原理分析打好基础。

参考资料

《一文搞懂Android JetPack组件原理之Lifecycle、LiveData、ViewModel与源码分析技巧》

你可能感兴趣的:(Android,JetPack,android,jetpack,viewmodel,源码分析,原理)