android - 如何用 Dagger2 @Inject AndroidViewModel?

标签 android dagger-2 android-viewmodel

我目前正在调查 Dagger2 的使用情况在我的 Android 应用程序中。

implementation 'com.google.dagger:dagger:2.21'
annotationProcessor 'com.google.dagger:dagger-compiler:2.21'

implementation 'com.google.dagger:dagger-android:2.21'
implementation 'com.google.dagger:dagger-android-support:2.21'
annotationProcessor 'com.google.dagger:dagger-android-processor:2.21'

我已经设法 @Inject ViewModel 及其关联的存储库

使用以下代码:-
import java.util.Map;

import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;

import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;

@Singleton
public class DaggerViewModelFactory implements ViewModelProvider.Factory {

    private final Map<Class<? extends ViewModel>, Provider<ViewModel>> creators;

    @Inject
    public DaggerViewModelFactory(final Map<Class<? extends ViewModel>, Provider<ViewModel>> creators) {
        this.creators = creators;
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T extends ViewModel> T create(final Class<T> modelClass) {
        Provider<? extends ViewModel> creator = creators.get(modelClass);

        if (creator == null) {
            for (Map.Entry<Class<? extends ViewModel>, Provider<ViewModel>> entry : creators.entrySet()) {
                if (modelClass.isAssignableFrom(entry.getKey())) {
                    creator = entry.getValue();
                    break;
                }
            }
        }

        if (creator == null) {
            throw new IllegalArgumentException("unknown model class " + modelClass);
        }

        try {
            return (T) creator.get();
        } catch (final Exception e) {
            throw new RuntimeException(e);
        }
    }
}

import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import dagger.Binds;
import dagger.Module;
import dagger.multibindings.IntoMap;

@Module
public abstract class ViewModelModule {

    @Binds
    abstract ViewModelProvider.Factory bindViewModelFactory(final DaggerViewModelFactory factory);

    @Binds
    @IntoMap
    @ViewModelKey(StilettoViewModel.class)
    abstract ViewModel provideStilettoViewModel(final StilettoViewModel stilettoViewModel);
}

但是我的一些 ViewModel 是 androidx.lifecycle.AndroidViewModel .

我创建了这个 ViewModelFactory:-
import android.app.Application;

import java.util.Map;

import javax.inject.Provider;
import javax.inject.Singleton;

import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;

@Singleton
public class DaggerAndroidViewModelFactory extends ViewModelProvider.AndroidViewModelFactory {

    private final Application application;

    private Map<Class<? extends AndroidViewModel>, Provider<AndroidViewModel>> creators;


    /**
     * Creates a {@code AndroidViewModelFactory}
     *
     * @param application an application to pass in {@link AndroidViewModel}
     */
    public DaggerAndroidViewModelFactory(@NonNull final Application application) {
        super(application);
        this.application = application;
    }


    @NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull final Class<T> modelClass) {
        return super.create(modelClass);
    }
}

和这个 Dagger 模块
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.ViewModelProvider;
import dagger.Binds;
import dagger.Module;
import dagger.multibindings.IntoMap;

@Module
public abstract class ViewModelModule {

    @Binds
    abstract ViewModelProvider.AndroidViewModelFactory bindAndroidViewModelFactory(final DaggerAndroidViewModelFactory factory);

    @Binds
    @IntoMap
    @ViewModelKey(MyAndroidViewModel.class)
    abstract AndroidViewModel provideArticlesViewModel(final ArticlesViewModel articlesViewModel);
}

当我收到此错误时,此代码将无法构建
error: [Dagger/MissingBinding] MyAndroidViewModel cannot be provided without an @Inject constructor or an @Provides-annotated method.

是否可以注入(inject)androidx.lifecycle.AndroidViewModel与 Dagger 2?

我的实现哪里出了问题?

最佳答案

如果您有 @Module@Provides Application (或者你使用 @BindsInstance + @Component.Builder ,老实说两者都有效):

@Module
public class AppModule {
    private final Application app;

    public AppModule(Application app) {
        this.app = app;
    }

    @Provides
    Application app() { return app; } 
}


@Component(modules={AppModule.class, ...})
@Singleton
public interface AppComponent {
}

然后现在而不是使用 AndroidViewModel:
public class MyViewModel extends AndroidViewModel {
    public MyViewModel(Application app) {
        ...
    }
}

您可以将常规 ViewModel 与 @Inject 一起使用构造函数:
public class MyViewModel extends ViewModel {
    @Inject
    MyViewModel(Application app) {
        ...
    }
}

您可以通过 DaggerViewModelFactory 像任何其他常规 ViewModel 类一样使用它。 .

关于android - 如何用 Dagger2 @Inject AndroidViewModel?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55142614/

相关文章:

android - 在 SQLite 数据库中完成更改后没有创建数据库

android - 如何通过在 Android 中使用内容 uri(_not_ 文件 uri)的 Intent 传递单个图像

android - 在 Android Activity 之间运行自定义动画

android - 使用 Dagger 2 提供函数依赖

dagger-2 - Dagger 1 到 2 迁移 - 成员注入(inject)方法只能返回注入(inject)的类型或 void

android - 如何在模块中添加 View 模型?

android - 当应用程序处于调试状态时,为什么 Gradle 在 Release模式下构建我的模块

android - 作为静态全局变量的 Dagger2 组件

android - 从 View 模型类中获取 Activity 的上下文

java - ViewModel 没有零参数构造函数错误 - 即使它具有零参数构造函数