2

私はRoboGuiceを使いましたが、廃止されました。私はDagger2で置き換え始めます。 Dagger2多くのアクティビティ/フラグメント/サービスを注入します(可能なNPEがたくさんあります)

// https://github.com/google/dagger 
compile('com.google.dagger:dagger:2.7') 
annotationProcessor 'com.google.dagger:dagger-compiler:2.7' 
provided 'org.glassfish:javax.annotation:10.0-b28' 

public class Application extends MultiDexApplication { 
    private ApplicationComponent mApplicationComponent; 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     mApplicationComponent = DaggerApplicationComponent.builder() 
       .applicationModule(new ApplicationModule(this)) 
       .build(); 
     mApplicationComponent.inject(this); 
    } 

    public static Application getApp(@NonNull Context context) { 
     return (Application) context.getApplicationContext(); 
    } 

    public static ApplicationComponent getApplicationComponent(@NonNull Context context) { 
     return getApp(context).getApplicationComponent(); 
    } 
} 

そして、私は例えばApplicationComponent

を注入したいときにどこでも後


@Module 
public class ApplicationModule { 
    Application mApp; 

    public ApplicationModule(@NonNull Application app) { 
     Preconditions.checkNotNull(app); 
     mApp = app; 
    } 

    @Provides 
    @Singleton 
    public SharedPreferences providesSharedPrefs() { 
     return PreferenceManager.getDefaultSharedPreferences(mApp); 
    } 

    @Provides 
    @Singleton 
    public DateHelper providesDateHelper() { 
     return new DateHelper(mApp); 
    } 

    @Provides 
    @Singleton 
    public PersistentConfig providesPersistentConfig() { 
     return new PersistentConfig(mApp); 
    } 

    @Provides 
    @Singleton 
    public OttoBus providesOttoBus() { 
     return new OttoBus(); 
    } 
} 
MainActivity

public class MainActivity extends AppCompatActivity { 
    @Inject 
    PersistentConfig mPersistentConfig; 

    @Inject 
    OttoBus mOttoBus; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     Helper.manageRotation(this); 
     super.onCreate(null); 
     setContentView(R.layout.main_layout); 
     Application.getApplicationComponent(this).inject(this); 
    } 
} 

Application.getApplicationComponent(context).inject(this);

最初の質問:私はinterface ApplicationComponentについて本当に困惑している私は、注射を使用する場所すべて活動/フラグメント/サービス(など)を提供する必要があります。しかし、Activity/Fragmentのような汎用オブジェクトは使用できません。または、私は実際には現実の外にあり、Dagger2の仕組みを理解できませんか?

これを約50+活動およびフラグメント/サービスのトンを使用したプロジェクトのために本当にクレイジーなので...

@Singleton 
@Component(modules = {ApplicationModule.class}) 
public interface ApplicationComponent { 
    void inject(@NonNull Application app); 
    void inject(@NonNull MainActivity object); 
    void inject(@NonNull DispatcherActivity object); 
    void inject(@NonNull DateTimeHelper object); 
    void inject(@NonNull DatabaseHelper object); 
    void inject(@NonNull LandingPageActivityFragment object); 
    void inject(@NonNull RedirectActivity object); 
    void inject(@NonNull CategoryFragment object); 
    void inject(@NonNull BaseModuleFragment object); 
    void inject(@NonNull NotificationHelper object); 
    void inject(@NonNull RecordAdapter object); 
    void inject(@NonNull PagingProvider object); 
    void inject(@NonNull FilterDialog object); 
    ... next 100+ injections? 
} 

...それは本当ではないことを、私に言いました2番目の質問: genericクラスを挿入する方法は、特定のオブジェクトが必要なのでvoid inject(@NonNull NotificationHelper<? extends GenericObject> object);のように使うことができません。だから私はこのオブジェクトをApplicationComponentの中に書いて、?表記を使わないでください。

RoboGuiceの方がはるかに開発者に親しみやすく、このオーバーヘッドと手動で注入されたすべてのオブジェクトをチェックする必要はありませんか?このリストに追加するのを忘れたときは(私はそれを、それは顧客をクラッシュする多くのことをテストしないとき)、実行時にNPEを取得します。

それははるかに速く、それはActivity/Fragment/Serviceのような一般的なオブジェクトを使用することはできませんときにすべてのオブジェクトのリストを作成するよりも、手動でそれを書くのです。

より良い解決策がありますか?同じ汎用品を使用したくない場合 ApplicationModuleとすべての活動はこの巨大なBaseActivityによって拡張されますか?

答えて

2

この質問は、苦情の側面を持っていますが、答えを試みるために:

私はインターフェイスApplicationComponentについては本当に困惑しているすべての活動/フラグメント/サービスを提供しなければならない(など)私は注射を使用したいです。しかし、私はActivity/Fragmentのような一般的なオブジェクトを使うことはできません。または、私は実際には現実の外にあり、Dagger2の仕組みを理解できませんか?

これは確かにDagger 2の仕組みです。インジェクタ(コンポーネント)内の注入ターゲットのタイプを静的に指定しなければならず、「汎用」(共変)タイプは使用できません。Dagger 2は100%静的なDIフレームワークを維持するためにこれを行います。

注入サイトとしてRecordAdapterおよびDatabaseHelperを指定していることに注意してください。あなたはおそらくそれを行う必要はありません。コンストラクタが表示されないトップレベルのオブジェクト(ActivityFragment、およびService)のみを注入サイトとして指定してください。残りのオブジェクトは、依存関係に@Injectを注釈付けし、依存関係がある場合はModuleに指定することで構築できます。

たぶんずっと開発者フレンドリーで、このオーバーヘッドを作る必要はありませんRoboGuiceとのより良い滞在と手動チェック、すべての注入されたオブジェクト

はいRoboguiceはそうしないという意味で、より友好的です注入ターゲットの指定について心配する必要があります。しかし、Roboguiceの次のような点を考慮してください。1.オブジェクトグラフを正しく設定しないと、「死の赤いスタックトレース」が発生する 2. Findでどのインタフェースの実装が実際にプロジェクトで使用されているのかわからないという事実また、「非友好的な開発者

ことができる用途は、よりよい解決策は、私がApplicationModuleのあらゆる部分を注入し、すべての活動は、この巨大なBaseActivityによって延長される同じジェネリックBaseActivityを使いたくない場合、ありますか?

これは、使用している依存関係と使用している場所によって異なります。依存関係の小さなリストがどこにでもある場合は、が最適です。すなわち、BaseActivityを注入してすべてのサブクラスで利用できるようにします。または、サブコンポーネントとモジュールを使用して、オブジェクトグラフを分割して、コンシューマ/インジェクションターゲットを適切なモジュールとともにグループ化することができます。次に、すべての注射部位を列挙する1つの「神」コンポーネントを持つ必要はありません。

2番目の質問:void inject(@NonNull NotificationHelperオブジェクト)のように使用できないときに、汎用クラスを挿入する方法を提供できます。特定のオブジェクトが必要なためです。だから、私はApplicationComponentの中にこのすべてのオブジェクトを書く必要がありますか?表記法?

はい、注入ターゲットの不変型を指定する必要があります。 NotificationHelper<String>がトップレベルのタイプであるかどうかはわかりません。 FragmentActivity、またはServiceに注入すると、オブジェクトグラフに注入されないのはなぜですか?

それは絶対にあなたがサブクラスにする必要があります注射対象でなければならない場合:NotificationHelper<String>Notification<Integer>StringNotificationHelper extends NotificationHelper<String>IntegerNotficationHelper extends NotificationHelper<Integer>なります。これは、「コードのクリーン」で推奨されている方法です。

すべての注入サイトをApplicationComponent内に記述する必要はありません。プロジェクト内の依存関係の消費パターンに対応するサブコンポーネントを作成することができます。

(開示:現在Roboguiceからダガー2にプロジェクトを移行しようとしている人として、私はあなたの苦情に同情しています)

1

おかげであなたは一週間前に説明したように、我々はそれを解決しました。注入されたすべてのオブジェクトを使用する。

それのためのより良い解決策は、injectだけを使用するのではなく、複雑な名前です。どうして?いくつかのオブジェクトが注入されない理由を解決するのに役立つので(あなたは知っている、ベースクラスなど)。 https://medium.com/@patrykpoborca/dagger-2-and-base-classes-generics-and-presenter-injection-7d82053080c#.b58ykd4cm

:ここに記載されているように我々は最終的にジェネリック UtilityWrapperに使用

@Singleton 
@Component(modules = {ApplicationModule.class}) 
public interface ApplicationComponent { 
    void injectApplication(@NonNull Application app); 
    void injectMainActivity(@NonNull MainActivity object); 
    void injectDispatcherActivity(@NonNull DispatcherActivity object); 
    ... 
} 

関連する問題