如果把Activity比喻成一栋大房子,LiveData就好比一个个家丁,那ViewModel就是那个大管家,他管理着房子的大大小小的事务和每个家丁的日常工作。
ViewModel的设计目的可以概况成以下几点:
1.维护Activity的数据不随着Activity的各种生命异常而丢失,比如手机的横竖屏切换的时候;
2.承担起Activity控制层的作用,让Activity的代码不至于太膨胀,便于维护;
3.在作用域可控的情况下管理各种异步请求和数据的生命敏感事件。
这就是谷歌给开发者的一套标准的开发app的指导方案,很权威,很nice,用完你会感叹相见恨晚。
先来看看ViewModel的创建,继承ViewModel即可:
class MainViewModel : ViewModel() {
// 维护了一个liveData
private val testLiveData = MutableLiveData(0)
// get方法只返回liveData,这样就实现了liveData的读写分离,在viewModel里更改,activity里读取
fun getTestLiveData(): LiveData<Int> {
return testLiveData
}
}
怎么实例化呢,官方不推荐直接new出来,而是这样:
class MainActivity : AppCompatActivity() {
private lateinit var mainViewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 官方推荐的实例化方式
mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
}
}
那就从ViewModelProvider开始入手,看看ViewModel是基于什么原理设计和维护的,先看看ViewModelProvider的构造方法和get方法:
public class ViewModelProvider {
// 维护了两个成员变量,实际上也都是他们俩在做事
private final Factory mFactory; // 创建ViewModel实例的工厂
private final ViewModelStore mViewModelStore; // 字面意思就是ViewModel存储类
//
public interface Factory {
/**
* Creates a new instance of the given {@code Class}.
* <p>
*
* @param modelClass a {@code Class} whose instance is requested
* @param <T> The type parameter for the ViewModel.
* @return a newly created ViewModel
*/
@NonNull
<T extends ViewModel> T create(@NonNull Class<T> modelClass);
}
// ViewModelStoreOwner是个接口,字面意思是ViewModelStore拥有者,根据谷歌jetpack代码命名规律也能猜到它的作用是能提供
//ViewModelStore ,我们在上面的示例传入了自身Activity this,说明父类实现了ViewModelStoreOwner接口。
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
// ComponentActivity也实现了HasDefaultViewModelProviderFactory,下面我们把它相关方法也贴出来
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
: NewInstanceFactory.getInstance());
}
// 最终给两个成员变量完成了赋值
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
mFactory = factory;
mViewModelStore = store;
}
@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");
}
// key加了DEFAULT_KEY 拼装起来
return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}
@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
// 先从mViewModelStore里取,这里猜测应该是个缓存
ViewModel viewModel = mViewModelStore.get(key);
// 如果是ViewModel的子类对象并且mFactory是OnRequeryFactory子类对象
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.
}
}
// 用相应的工厂创建ViewModel实例
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
} else {
viewModel = mFactory.create(modelClass);
}
// 放入缓存
mViewModelStore.put(key, viewModel);
return (T) viewModel;
}
...略
}
ViewModelProvider的两个成员变量mViewModelStore 和mFactory 分别来自ComponentActivity的getViewModelStore()和getDefaultViewModelProviderFactory() 方法:
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
...
ViewModelStoreOwner,
HasDefaultViewModelProviderFactory,
SavedStateRegistryOwner {
@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.");
}
// 这个方法就是创建了一个ViewModelStore赋值给了mViewModelStore
ensureViewModelStore();
return mViewModelStore;
}
@NonNull
@Override
public final SavedStateRegistry getSavedStateRegistry() {
return mSavedStateRegistryController.getSavedStateRegistry();
}
@NonNull
@Override
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) {
// 创建的是SavedStateViewModelFactory,看命名是保存状态的vm工厂,注意这个构造函数穿了些啥
mDefaultFactory = new SavedStateViewModelFactory(
getApplication(),
this,
getIntent() != null ? getIntent().getExtras() : null);
}
return mDefaultFactory;
}
}
// ViewModelStore 专门用来存储ViewModel
public class ViewModelStore {
// 熟悉的存储方式,map
private final HashMap<String, ViewModel> mMap = new HashMap<>();
// 存储
final void put(String key, ViewModel viewModel) {
ViewModel oldViewModel = mMap.put(key, viewModel);
// 如果之前存储了相同的,执行一下onCleared方法
if (oldViewModel != null) {
oldViewModel.onCleared();
}
}
// 取缓存
final ViewModel get(String key) {
return mMap.get(key);
}
Set<String> keys() {
return new HashSet<>(mMap.keySet());
}
/**
* 清除所有的viewModel
*/
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
// 注意会执行viewModel的clear方法
mMap.clear();
}
}
注意:其实到这里你基本应该已经知道了ViewModel是怎么被创建和保存起来的了,以下内容只是探寻ViewModel究竟是怎么被实例化的,提前透露一下就是用类名通过newInstance()实例化的。
现在做个小总结:ViewModel如果通过ViewModelProvider的get方法实例化的话,同一个Activity(ViewModelStoreOwner)里只会实例化一个实例然后缓存到ViewModelStore里,每次获取的时候是会先取缓存,所以保证了同一个ViewModel的唯一性!
再来看SavedStateViewModelFactory:
public final class SavedStateViewModelFactory extends ViewModelProvider.KeyedFactory {
private final Application mApplication;
private final ViewModelProvider.Factory mFactory; // 实际是这个工厂在创建vm实例
private final Bundle mDefaultArgs;
private final Lifecycle mLifecycle; // 维护了一个lifecycle
private final SavedStateRegistry mSavedStateRegistry; // 所谓的保存状态应该跟这个有关
public SavedStateViewModelFactory(@Nullable Application application,
@NonNull SavedStateRegistryOwner owner) {
this(application, owner, null);
}
@SuppressLint("LambdaLast")
public SavedStateViewModelFactory(@Nullable Application application,
@NonNull SavedStateRegistryOwner owner,
@Nullable Bundle defaultArgs) {
mSavedStateRegistry = owner.getSavedStateRegistry();
mLifecycle = owner.getLifecycle();
mDefaultArgs = defaultArgs;
mApplication = application;
// 前面调用这个构造函数是传下来了application的,所以这里执行的是
// ViewModelProvider.AndroidViewModelFactory.getInstance(application)
mFactory = application != null
? ViewModelProvider.AndroidViewModelFactory.getInstance(application)
: ViewModelProvider.NewInstanceFactory.getInstance();
}
// 这里是ViewModelProvider里创建viewModel调用的方法
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass) {
// 我们创建一般的ViewModel,不是继承自AndroidViewModel,所以是false
boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass);
Constructor<T> constructor;
if (isAndroidViewModel && mApplication != null) {
constructor = findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE);
} else {
// 所以会命中这里,去找匹配的构造函数,这个方法在下面
constructor = findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE);
}
// doesn't need SavedStateHandle
//不需要SavedStateHandle ,至于需要的情况那是另外的应用场景,可以单独去了解
if (constructor == null) {
// 绕了半天,其实还是执行了这个创建方法,我们继续看AndroidViewModelFactory
return mFactory.create(modelClass);
}
// 这里的逻辑是关于SavedStateHandle ,暂不细看
SavedStateHandleController controller = SavedStateHandleController.create(
mSavedStateRegistry, mLifecycle, key, mDefaultArgs);
try {
T viewmodel;
if (isAndroidViewModel && mApplication != null) {
viewmodel = constructor.newInstance(mApplication, controller.getHandle());
} else {
viewmodel = constructor.newInstance(controller.getHandle());
}
viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller);
return viewmodel;
} 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());
}
}
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
// ViewModelProvider calls correct create that support same modelClass with different keys
// If a developer manually calls this method, there is no "key" in picture, so factory
// simply uses classname internally as as key.
String canonicalName = modelClass.getCanonicalName();
if (canonicalName == null) {
throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
}
return create(canonicalName, modelClass);
}
private static final Class<?>[] ANDROID_VIEWMODEL_SIGNATURE = new Class[]{Application.class,
SavedStateHandle.class};
private static final Class<?>[] VIEWMODEL_SIGNATURE = new Class[]{SavedStateHandle.class};
@SuppressWarnings("unchecked")
private static <T> Constructor<T> findMatchingConstructor(Class<T> modelClass,
Class<?>[] signature) {
for (Constructor<?> constructor : modelClass.getConstructors()) {
// 这里会去找入参是SavedStateHandle类型的构造函数,显然我们一般的
//ViewModel是没有这个构造函数的,这里会返回null,我们继续回到上面
Class<?>[] parameterTypes = constructor.getParameterTypes();
if (Arrays.equals(signature, parameterTypes)) {
return (Constructor<T>) constructor;
}
}
return null;
}
@Override
void onRequery(@NonNull ViewModel viewModel) {
attachHandleIfNeeded(viewModel, mSavedStateRegistry, mLifecycle);
}
}
public open class AndroidViewModelFactory( private val application: Application) : NewInstanceFactory() {
// 通过上面的分析我们知道是调用了这个方法来创建ViewModel的
override fun <T : ViewModel> create(modelClass: Class<T>): T {
// 上面我们也分析过我们的viewModel不是AndroidViewModel的子类
return if (AndroidViewModel::class.java.isAssignableFrom(modelClass)) {
try {
modelClass.getConstructor(Application::class.java).newInstance(application)
} catch (e: NoSuchMethodException) {
throw RuntimeException("Cannot create an instance of $modelClass", e)
} catch (e: IllegalAccessException) {
throw RuntimeException("Cannot create an instance of $modelClass", e)
} catch (e: InstantiationException) {
throw RuntimeException("Cannot create an instance of $modelClass", e)
} catch (e: InvocationTargetException) {
throw RuntimeException("Cannot create an instance of $modelClass", e)
}
// 所以最终是调用了父类的create方法,下面接着看父类NewInstanceFactory
} else super.create(modelClass)
}
}
public open class NewInstanceFactory : Factory {
@Suppress("DocumentExceptions")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return try {
// 好嘛,最后就是简单的反射创建的
modelClass.newInstance()
} catch (e: InstantiationException) {
throw RuntimeException("Cannot create an instance of $modelClass", e)
} catch (e: IllegalAccessException) {
throw RuntimeException("Cannot create an instance of $modelClass", e)
}
}
...略
}
网友评论