Кинжал 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-инъекцию - любая помощь будет принята с благодарностью.
Ответы
Ответ 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;
}
}