MVVM之viewModel与model的实例化

459 阅读1分钟

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;
    }