[英]How do I get a ViewModel without ViewModelProviders class?
[英]ViewModelProviders.get(…) in base class
我试图通过在抽象基类中移动我的一些ViewModel实例来削减Dagger的一些样板,但是找不到很好的方法来做到这一点。 我的目的是从我的基本片段中实例化我的所有ViewModel,以便它们可以被所有子片段使用,而不必让它们进行自己的实例化。 我的问题在于使用泛型(VM)检索ViewModel - 具体在这里: .get(viewModel::class.java)
。 我还尝试了不允许的.get(VM::class.java)
BaseFragment
abstract class BaseFragment<VM : ViewModel> : Fragment() {
@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
lateinit var viewModel : VM
override fun onAttach(context: Context?) {
super.onAttach(context)
viewModel = ViewModelProviders.of(this, viewModelFactory).get(viewModel::class.java)
}
}
ViewModelProviders.get(...)方法签名
public <T extends ViewModel> T get(@NonNull Class<T> modelClass)
这甚至可能吗?
val viewModel: T by lazy {
ViewModelProviders.of(this).get(getTClass())
}
//获取泛型T的实际类型
private fun getTClass(): Class<T> {
return (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<T>
}
如果你有一个像这样定义的BaseFragment
:
public class BaseFragment<T extends ViewModel> extends Fragment {
@Inject
protected T viewModel;
}
您可以使用Architecture Components的Github浏览器示例中的ViewModelUtils类来创建ViewModel
工厂。
/**
* Creates a one off view model factory for the given view model instance.
*/
public class ViewModelUtil {
private ViewModelUtil() {}
public static <T extends ViewModel> ViewModelProvider.Factory createFor(T model) {
return new ViewModelProvider.Factory() {
@Override
public <T extends ViewModel> T create(Class<T> modelClass) {
if (modelClass.isAssignableFrom(model.getClass())) {
return (T) model;
}
throw new IllegalArgumentException("unexpected model class " + modelClass);
}
};
}
}
在BaseFragment
的onActivityCreated
方法中,您可以添加
@Override
public void onActivityCreated(@Nullable final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ViewModelProvider.Factory viewModelFactory = ViewModelUtil.createFor(viewModel);
ViewModelProviders.of(this, viewModelFactory).get(viewModel.getClass());
}
此技术的代码来自此博客文章 。
我有同样的问题,但用一点反思修复它; 我真的不喜欢在Android上使用Reflection,但没有其他选择。
private void initViewModel() {
final Type[] types = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments();
mViewModel = ViewModelProviders.of(this).get((Class<M>) types[0]);
}
希望这对某人有用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.