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

ben*_*ben 7 android kotlin dagger-2

我试图通过在抽象基类中移动一些ViewModel实例来削减Dagger的样板,但是找不到一个很好的方法来做到这一点。我的目的是实例化我的基本片段中的所有ViewModel,以使它们可供所有子片段使用,而无需它们自己进行实例化。我的问题在于使用通用(VM)检索ViewModel-具体在此处:.get(viewModel::class.java)。我也尝试.get(VM::class.java)过不允许

基本片段

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

ViewModelProviders.get(...)方法签名

public <T extends ViewModel> T get(@NonNull Class<T> modelClass)
Run Code Online (Sandbox Code Playgroud)

这有可能吗?

Lor*_*nMK 5

如果你有这样的BaseFragment定义:

public class BaseFragment<T extends ViewModel> extends Fragment {

    @Inject
    protected T viewModel;

}
Run Code Online (Sandbox Code Playgroud)

您可以使用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);
            }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

在你可以添加的onActivityCreated方法中BaseFragment

    @Override
    public void onActivityCreated(@Nullable final Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        ViewModelProvider.Factory viewModelFactory = ViewModelUtil.createFor(viewModel);
        ViewModelProviders.of(this, viewModelFactory).get(viewModel.getClass());
    }
Run Code Online (Sandbox Code Playgroud)

此技术的代码来自此博客文章


小智 5

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>
}
Run Code Online (Sandbox Code Playgroud)