web-dev-qa-db-ja.com

ダガー2インジェクトAndroid Context

私はDagger 2を使用していますが、動作していますが、Android Application Context。

コンテキストにインジェクトしてアクセスする方法は明確ではありません。私はこれを次のようにしようとしました:

@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を設定する必要があります

Daggerで生成されたコードを調べると、この例外が発生します。

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

これがコンテキストをインジェクトする正しい方法であるかどうかはわかりません。どんな助けでも大歓迎です。

30
user3521637

アプリケーションを渡すために必要なアプリケーションコンポーネントを正しく構築していませんでした。このDagger 2の例は、これを行う方法を完全に示しています。 https://github.com/google/dagger/tree/master/examples/Android-simple/src/main/Java/com/example/dagger/simple

更新:
作業リンク: https://github.com/yongjhih/dagger2-sample/tree/master/examples/Android-simple/src/main/Java/com/example/dagger/simple

1
user3521637
@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();
24
EpicPandaForce

適切な解決策を見つけるのに時間がかかったので、現在のDaggerバージョン(2.22.1)で推奨される解決策である限り、他の人にとっては時間を節約できると思いました。

次の例では、Applicationを作成するためにContextRoomDatabaseが必要です(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;
    }
}
1
keisar