MVVM架构中,viewmodel的实例化是通过ViewModelProviders通过NewInstanceFactory的create方法实现的 实现方法有以下两种方式:
//使用默认ViewModelProvider.NewInstanceFactory
ViewModelProviders.of(this).get(getViewModel());
//使用自定义ViewModelProvider.NewInstanceFactory
ViewModelProviders.of(this,MainViewModelFactory.getInstance(application)).get(getViewModel());
在create方法中实例化viewModel,传递参数application 和model,同时也实例化了model
public class MainViewModelFactory extends ViewModelProvider.NewInstanceFactory {
@SuppressLint("StaticFieldLeak")
private static volatile MainViewModelFactory INSTANCE;
private final Application mApplication;
public static MainViewModelFactory getInstance(Application application) {
if (INSTANCE == null) {
synchronized (MainViewModelFactory.class) {
if (INSTANCE == null) {
INSTANCE = new MainViewModelFactory(application);
}
}
}
return INSTANCE;
}
private MainViewModelFactory(Application application) {
this.mApplication = application;
}
@VisibleForTesting
public static void destroyInstance() {
INSTANCE = null;
}
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
if (modelClass.isAssignableFrom(MainViewModel.class)) {
return (T) new MainViewModel(mApplication, new MainModel(mApplication));
}
throw new IllegalArgumentException("Unknown ViewModel class: " + modelClass.getName());
}
}
//model也可以在viewmodel中通过泛型+反射实例化
public class BaseViewModel<M extends BaseModel> extends ViewModel {
public M model;
public BaseViewModel() {
try {
ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
Class<M> modelClazz = (Class<M>) type.getActualTypeArguments()[0];
model = modelClazz.newInstance();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
我们再来看看源码中viewmodel是如何一步步实例化的
1.ViewModelProviders中实例化ViewModelProvider
public static ViewModelProvider of(@NonNull FragmentActivity activity,
@Nullable Factory factory) {
Application application = checkApplication(activity);
if (factory == null) {
factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
}
//可以看到ViewModelStore是与activity绑定的,因此同一个activity中viewmodel是可以重复利用的
return new ViewModelProvider(activity.getViewModelStore(), factory);
}
2.ViewModelProvider中get方法首先用viewmodel的类全名拼出key
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);
}
3.然后通过factory的create方法实例化viewmodel,然后以key标识存储在mViewModelStore中,下次可以直接用key从mViewModelStore中获取
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
ViewModel viewModel = mViewModelStore.get(key);
if (modelClass.isInstance(viewModel)) {
//noinspection unchecked
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);
//noinspection unchecked
return (T) viewModel;
}