gpt4 book ai didi

java - 架构组件 : How does the ViewModelProvider know which constructor to call?

转载 作者:太空宇宙 更新时间:2023-11-03 13:11:15 24 4
gpt4 key购买 nike

我一直在阅读有关引入到 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;
}
}
}

这里是 kotlin version .这是 more read on the subject

关于java - 架构组件 : How does the ViewModelProvider know which constructor to call?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44618769/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com