- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我一直在阅读有关引入到 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;
}
}
摘自指南的 fragment :https://developer.android.com/topic/libraries/architecture/guide.html
但是,稍后在指南中有这个 fragment :
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 是如何知道调用提供的构造函数的呢?或者它看到只有 1 个构造函数并调用它?例如,如果有 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)
如何工作?
最佳答案
在代码 fragment 中有一个条件检查 modelClass 是否属于 AndroidViewModel
类型(继承 ViewModel
)构造函数采用 Application
参数。这更像是独占情况,它使 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;
}
}
}
关于java - 架构组件 : How does the ViewModelProvider know which constructor to call?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44618769/
我是一名优秀的程序员,十分优秀!