架构组件:ViewModelProvider如何知道调用哪个构造函数?

我一直在阅读介绍给Android的新架构组件,我无法弄清楚它是如何工作的:

ViewModelProviders.of(Activity).get(Class) 

最初我以为它调用默认的构造函数,并返回一个ViewModel对象,然后你用例如实例化。 一个init()方法

 public class UserProfileViewModel extends ViewModel { private String userId; private User user; public void init(String userId) { this.userId = userId; } public User getUser() { return user; } } 

摘自该指南的摘录: https : //developer.android.com/topic/libraries/architecture/guide.html

然而,在指南的后面有这个片段:

 public class UserProfileViewModel extends ViewModel { private LiveData<User> user; private UserRepository userRepo; @Inject // UserRepository parameter is provided by Dagger 2 public UserProfileViewModel(UserRepository userRepo) { this.userRepo = userRepo; } public void init(String userId) { if (this.user != null) { // ViewModel is created per Fragment so // we know the userId won't change return; } user = userRepo.getUser(userId); } 

那么ViewModelProvider如何知道如何调用提供的构造函数呢? 或者它看到只有一个构造函数并调用它? 例如,如果有2个构造函数会发生什么?

我试着通过代码挖掘,我发现的是:

 @Override public <T extends ViewModel> T create(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); } 

ViewModelProviders.java内部的DefaultFactory类中。 但是,这使我更加困惑。 当ViewModel对象没有一个将Application作为参数的构造函数时, getConstructor(Application.class)如何工作?

在代码片段中有一个条件,它检查modelClass是否为构造函数带有 Application参数的AndroidViewModel类型(继承ViewModel )。 这更像是独占的情况下,查找与特定参数匹配的构造函数的Factory 。 此提供程序在创建时查找构造函数匹配的提供者参数:

 public class ViewModelParameterizedProvider { private AtomicBoolean set = new AtomicBoolean(false); private ViewModelStore viewModelStore = null; static ViewModelParameterizedProvider getProvider() { return new ViewModelParameterizedProvider(); } @MainThread public static ViewModelProvider ofSupportFragment(Fragment fragment, Object... params) { return getProvider().of(fragment).with(params); } @MainThread public static ViewModelProvider ofActivity(FragmentActivity fragmentActivity, Object... params) { return getProvider().of(fragmentActivity).with(params); } @MainThread public static ViewModelProvider ofFragment(android.app.Fragment fragment, Object... params) { return getProvider().of(fragment).with(params); } private ViewModelParameterizedProvider of(Fragment fragment) { checkForPreviousTargetsAndSet(); viewModelStore = ViewModelStores.of(fragment); return this; } private ViewModelParameterizedProvider of(android.app.Fragment fragment) { FragmentActivity fragAct = (FragmentActivity) fragment.getActivity(); return of(fragAct); } private ViewModelParameterizedProvider of(FragmentActivity activity) { checkForPreviousTargetsAndSet(); viewModelStore = ViewModelStores.of(activity); return this; } private ViewModelProvider with(Object... constructorParams) { return new ViewModelProvider(viewModelStore, parametrizedFactory(constructorParams)); } private void checkForPreviousTargetsAndSet() { if (set.get()) { throw new IllegalArgumentException("ViewModelStore already has been set. Create new instance."); } set.set(true); } private ViewModelProvider.Factory parametrizedFactory(Object... constructorParams) { return new ParametrizedFactory(constructorParams); } private final class ParametrizedFactory implements ViewModelProvider.Factory { private final Object[] mConstructorParams; ParametrizedFactory(Object... constructorParams) { mConstructorParams = constructorParams; } @Override public <T extends ViewModel> T create(Class<T> modelClass) { if (modelClass == null) { throw new IllegalArgumentException("Target ViewModel class can not be null") } Log.w("ParametrizedFactory", "Don't use callbacks or Context parameters in order to avoid leaks!!") try { if (mConstructorParams == null || mConstructorParams.length == 0) { return modelClass.newInstance(); } else { Class<?>[] classes = new Class<?>[mConstructorParams.length]; for (int i = 0; i < mConstructorParams.length; i++) { classes[i] = mConstructorParams[i].getClass(); } return modelClass.getConstructor(classes).newInstance(mConstructorParams); } } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return null; } } } 

这里是kotlin版本 。 这里有更多关于这个问题的文章