Dao имеет значение null при использовании Dagger2

#java #android #android-room #dagger-2

#java #Android #android-комната #dagger-2

Вопрос:

Когда я вызываю DAO в presenter, он возвращает null и вызывает NPE. Некоторый код здесь: класс DAO

 @Dao
public interface ElementsDao {
    @Query("SELECT * FROM   `elements`")
    Flowable<List<Elements>> getAll();

    @Insert
    Maybe<Long> insert(Elements element);...
}
 

классы модулей:

 @Module
public class DatabaseModule {

    private AppDatabase appDatabase;
    public DatabaseModule(Application mApplication){
        appDatabase = Room.databaseBuilder(mApplication, AppDatabase.class,"dbWarehouse")
                .setJournalMode(RoomDatabase.JournalMode.TRUNCATE)
                .build();
    }

    @Singleton
    @Provides
    public AppDatabase provideDatabase(){
        return appDatabase;
    }

    @Singleton
    @Provides
    ElementsDao providesElementsDao(AppDatabase appDatabase){
        return appDatabase.getElementsDao();
    }
}

@Module
public class AppModule {
    Application mApplication;

    public AppModule(Application application){
        mApplication = application;
    }

    @Provides
    @Singleton
    Application providesApplication() {
        return mApplication;
    }
}
 

Класс компонента

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

    void inject(MainActivity mainActivity);
    void inject(ElementsActivity elementsActivity);
    void inject(ActivityElementsPresenter activityElementsPresenter);

    ElementsDao elementsDao();

    AppDatabase appDatabase();

    Application application();
}
 

Класс приложения (объявленный в манифесте)

 public class App extends Application {
    private static AppComponent appComponent;
    @Override
    public void onCreate() {
        super.onCreate();
        initDagger();
    }
    private void initDagger(){
        appComponent = DaggerAppComponent.builder()
                .appModule(new AppModule(this))
                .databaseModule(new DatabaseModule(this))
                .build();
    }

    public static AppComponent getAppComponent() {
        return appComponent;
    }
}
 

И presenter

 @InjectViewState
public class ActivityElementsPresenter extends MvpPresenter<ActivityElementsView> {
    @Inject
    ElementsDao elementsDao;

    public void addElement(Elements element){
        elementsDao.insert(element).subscribeOn(Schedulers.io())...
 

Обновить
Класс AppDatabase

 @Database(entities = {Elements.class}, version = 1, exportSchema = false)
@TypeConverters({Converters.class})
public abstract class AppDatabase extends RoomDatabase {
    public abstract ElementsDao getElementsDao();
    //...
}
 

Во время отладки я установил точку в presenter и увидел, что dao не инициализирован
elementsDao

Пытаюсь использовать что-то вроде App.getAppComponent().elementsDao(); , но это тоже работает.

Комментарии:

1. можете ли вы добавить код AppDatabase класса

2. не здесь, добавьте к вашему вопросу, здесь он не читается.

3. @rahat извините, вопрос обновлен

4. Как вы получаете экземпляр ActivityElementsPresenter ?

5. можете ли вы добавить код MvpPresenter , который MvpPresenter является базовым классом для всех presenter?

Ответ №1:

Вам нужно сделать это таким образом,

 @InjectViewState
public class ActivityElementsPresenter extends MvpPresenter<ActivityElementsView> {
    @Inject
    ElementsDao elementsDao;

    public ActivityElementsPresenter(){
       App.getAppComponent().inject(this);//calling the dagger's injector to inject dependency.
    }

    public void addElement(Elements element){
        elementsDao.insert(element).subscribeOn(Schedulers.io())...
    }
}
 

Затем в

 @Singleton
@Component(dependencies = {},modules = {AppModule.class, DatabaseModule.class})
public interface AppComponent {
    void inject(MainActivity mainActivity);
    void inject(ElementsActivity elementsActivity);
    void inject(ActivityElementsPresenter activityElementsPresenter);//will inject dependency to ActivityElementsPresenter.  
}
 

Комментарии:

1. Теперь для каждого докладчика вам нужно добавить один абстрактный метод в AppComponent и вызвать inject метод в конструкторе.

2. Если вы используете шаблон BasePresenter, то внедрение будет проще для вас.