Подтвердить что ты не робот

Кинжал 2, вводящий Android Context

Я использую Dagger 2 и работаю, но теперь мне нужен доступ к Контексту приложений Android.

Неясно, как вводить и получать доступ к контексту. Я попытался сделать это следующим образом:

@Module
public class MainActivityModule {    
    private final Context context;

    MainActivityModule(Context context) {
        this.context = context;
    }

@Provides @Singleton
Context provideContext() {
    return context;
}

Однако это приводит к следующему исключению:

java.lang.RuntimeException: невозможно создать приложение: java.lang.IllegalStateException: mainActivityModule должен быть установлен

Если я проверю код сгенерированного кинжалом, здесь возникает это исключение:

public Graph build() {  
    if (mainActivityModule == null) {
        throw new IllegalStateException("mainActivityModule must be set");
    }
    return new DaggerGraph(this);
}

Я не уверен, что это правильный способ получить Context-инъекцию - любая помощь будет принята с благодарностью.

4b9b3361

Ответ 1

Не удалось правильно создать компонент приложения, необходимый для передачи в приложении. Этот пример Dagger 2 отлично показывает, как это сделать: https://github.com/google/dagger/tree/master/examples/android-simple/src/main/java/com/example/dagger/simple

Update:
Рабочая ссылка: https://github.com/yongjhih/dagger2-sample/tree/master/examples/android-simple/src/main/java/com/example/dagger/simple

Ответ 2

@Module
public class MainActivityModule {    
    private final Context context;

    public MainActivityModule (Context context) {
        this.context = context;
    }

    @Provides //scope is not necessary for parameters stored within the module
    public Context context() {
        return context;
    }
}

@Component(modules={MainActivityModule.class})
@Singleton
public interface MainActivityComponent {
    Context context();

    void inject(MainActivity mainActivity);
}

И затем

MainActivityComponent mainActivityComponent = DaggerMainActivityComponent.builder()
    .mainActivityModule(new MainActivityModule(MainActivity.this))
    .build();

Ответ 3

Мне потребовалось некоторое время, чтобы найти правильное решение, поэтому я подумал, что это может сэкономить время для других, насколько я понимаю, это предпочтительное решение с текущей версией Dagger (2.22.1).

В следующем примере мне нужен Context Application для создания RoomDatabase (происходит в StoreModule).

Пожалуйста, если вы видите какие-либо ошибки или ошибки, дайте мне знать, чтобы я тоже учился :)

Составная часть:

// We only need to scope with @Singleton because in StoreModule we use @Singleton
// you should use the scope you actually need
// read more here https://google.github.io/dagger/api/latest/dagger/Component.html
@Singleton
@Component(modules = { AndroidInjectionModule.class, AppModule.class, StoreModule.class })
public interface AwareAppComponent extends AndroidInjector<App> {

    // This tells Dagger to create a factory which allows passing 
    // in the App (see usage in App implementation below)
    @Component.Factory
    interface Factory extends AndroidInjector.Factory<App> {
    }
}

AppModule:

@Module
public abstract class AppModule {
    // This tell Dagger to use App instance when required to inject Application
    // see more details here: https://google.github.io/dagger/api/2.22.1/dagger/Binds.html
    @Binds
    abstract Application application(App app);
}

StoreModule:

@Module
public class StoreModule {
    private static final String DB_NAME = "aware_db";

    // App will be injected here by Dagger
    // Dagger knows that App instance will fit here based on the @Binds in the AppModule    
    @Singleton
    @Provides
    public AppDatabase provideAppDatabase(Application awareApp) {
        return Room
                .databaseBuilder(awareApp.getApplicationContext(), AppDatabase.class, DB_NAME)
                .build();
    }
}

Приложение:

public class App extends Application implements HasActivityInjector {

    @Inject
    DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;

    @Override
    public void onCreate() {
        super.onCreate();

        // Using the generated factory we can pass the App to the create(...) method
        DaggerAwareAppComponent.factory().create(this).inject(this);
    }

    @Override
    public AndroidInjector<Activity> activityInjector() {
        return dispatchingAndroidInjector;
    }
}