基类中的ViewModelProviders.get(...)

时间:2018-02-20 19:09:49

标签: android kotlin dagger-2

我试图通过在抽象基类中移动我的一些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)

这甚至可能吗?

3 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:2)

如果您的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);
            }
        };
    }
}

onActivityCreated的{​​{1}}方法中,您可以添加

BaseFragment

此技术的代码来自this blog post

答案 2 :(得分:0)

我有同样的问题,但用一点反思修复它;我真的不喜欢在Android上使用Reflection,但没有其他选择。

private void initViewModel() {
    final Type[] types = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments();
    mViewModel = ViewModelProviders.of(this).get((Class<M>) types[0]);
}

希望这对某人有用。