Dagger 2.11およびAndroid。 パート2

前の記事で 、特別なdagger-androidモジュールを使用して、アクティビティとフラグメントの依存関係、および異なるスコープの構成を提供する方法を検討しました。







この記事では、モジュールのコンポーネントを検討し、Androidの他の基本コンポーネントでの依存関係の提供を検討し、動的パラメーターで依存関係を提供するためのオプションも検討します。







dagger-androidモジュールを使用すると、次の基本的なAndroidコンポーネントに依存関係を注入できます。







Activity, Fragment, Service, DaggerIntentService, BroadcastReceiver, ContentProvider.









サポートライブラリのクラス( AppCompatActivity, android.support.v4.app.Fragment



)を使用する場合、追加のダガーサポートライブラリ(dagger-android-support)の対応するクラスを使用する必要があります。







AndroidInjector



基本コンポーネント( Activity, Fragment, ..



)の継承者に依存関係を注入します。







@ContributesAndroidInjector





この注釈は、モジュールの抽象メソッドに適用する必要があります。メソッドの戻り値の型は、基本的なandroidコンポーネント( Activity, Fragment ..



)の相続人です。 メソッドにパラメーターを含めることはできません。







このアノテーションは、アノテーションが示されているメソッドの戻り値の型のAndroidInjector



を生成するために使用されます。 このAndroidInjector



はサブコンポーネントです。 このサブコンポーネントは、このモジュール(このアノテーションが存在する)が追加されるコンポーネント(またはサブコンポーネント)の子です。







注釈には、 modules



パラメーターが含まれています。 このパラメーターは、この生成されたサブコンポーネントに追加されるモジュールを示します。







アノテーション@ContributesAndroidInjector



持つメソッドの上@ContributesAndroidInjector



アノテーションも存在@ContributesAndroidInjector



あります。 このスコープは、生成されたサブコンポーネントに適用されます。







AndroidInjectionModule / AndroidSupportInjectionModule



組み込みの短剣アンドロイドライブラリモジュール。 ルートコンポーネントに追加する必要があります。

@ContributesAndroidInjector



アノテーションを使用して生成されたサブコンポーネントを作成するためのファクトリーを備えたコレクションの複数の組み合わせが含まれています。 Androidの各基本コンポーネントには、独自のコレクションがあります。







AndroidInjectorのディスパッチ



これはAndroidInector



プロキシであり、特定のタイプのサブコンポーネント( AndroidInjector



)を作成するためのファクトリーのコレクションが含まれています。 たとえば、 DispatchingAndroidInjector<Activity>



は、 Activity



継承者のすべてのサブコンポーネント作成ファクトリが含まれます。 注入するとき、目的のファクトリを検索し、サブコンポーネント( AndroidInject



)を作成し、依存関係を注入します。







AndroidInjection / AndroidSupportInjection



ユーティリティクラスには、すべてのベースタイプ( Activity, Fragment, Service ..



)に対してオーバーロードされたinject



メソッドがあります。 渡されたタイプに応じて、次のインターフェースのいずれかの実装を検索します。









短剣アンドロイドサポート









目的のAndroidInject



を含む目的のインターフェイスの実装の検索は、ライフタイムが長いオブジェクトで行われます。

HasActivityInjector, HasServiceInjector, HasContentProviderInjector, HasBroadcastReceiverInjector



各インターフェイスをアプリケーションに実装する必要があります。 HasFragmentInjector



またはHasSupportFragmentInjector



は、フラグメントまたはアクティビティまたはapplication



に実装application



。実装は、親フラグメント、このフラグメントが配置されているアクティビティ、およびapplication



順序で検索されapplication









AndroidInjection.inject()



は、スーパーメソッドを呼び出す前に、特定のメソッドで呼び出す必要があります。









Dagger-androidには使用できるクラスがあります(これらのクラスは既に必要なインターフェイスを実装し、 AndroidInjection.inject()



メソッドを呼び出しています):









短剣アンドロイドサポート









何らかの理由でこれらのクラスのいずれかを拡張できない場合、必要なインターフェイスをいつでも実装できます。







短剣クラスの使用例:



メインコンポーネントを定義します。

コンポーネントがAndroidInjector



継承する必要があるのは、 DaggerApplication



を使用する場合、 AndroidInjector



が返すメソッドを1つ実装する必要があります。 これは、 application



に対してのみ行う必要がありapplication



。 メインコンポーネントを手動で識別します。







 @Component(modules = {AppModule.class, AndroidSupportInjectionModule.class}) @Singleton public interface AppComponent extends AndroidInjector<App> { @Component.Builder abstract class Builder extends AndroidInjector.Builder<App> {} }
      
      





メインモジュールを定義する







このモジュールでは、アクティビティ、サービス、およびブロードキャストレシーバーの「マッピング」を追加します。 サブコンポーネントがそれらに対して生成され、メインコンポーネントに追加されます。 このモジュールをメインコンポーネントに接続しました。







 @Module abstract public class AppModule { @Provides @Singleton public static Context context(App app) { return app.getApplicationContext(); } @Provides @Singleton public static UserRepository userRepository(Context context) { return new UserRepositoryImpl(context); } @ContributesAndroidInjector(modules = { ActivityModule.class }) @ActivityScope abstract MainActivity mainActivity(); @ContributesAndroidInjector(modules = { ServiceModule.class }) @ServiceScope abstract MyIntentService myIntentService(); @ContributesAndroidInjector @ReceiverScope abstract SomeReceiver connectionReceiver(); }
      
      





アプリケーションクラスを定義する







 public class App extends DaggerApplication { @Override protected AndroidInjector<? extends DaggerApplication> applicationInjector() { return DaggerAppComponent.builder().create(this); } }
      
      





活動例







 public class MainActivity extends DaggerAppCompatActivity { @Inject UserRepository userRepository; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //userRepository    } }
      
      





IntentServiceを使用した例







 public class MyIntentService extends DaggerIntentService { @Inject UserRepository userRepository; public MyIntentService() { super("MyIntentService"); } @Override protected void onHandleIntent(@Nullable Intent intent) { //userRepository    } }
      
      





受信機の例







 public class SomeReceiver extends DaggerBroadcastReceiver { @Inject UserRepository userRepository; @Override public void onReceive(Context context, Intent intent) { super.onReceive(context, intent); //userRepository    } }
      
      





コンポーネントのライフサイクル



dagger-androidを使用する場合、コンポーネントとサブコンポーネントは、作成されたAndroidコンポーネント( Activity, Fragment, Service



など)の存続期間中存続し、手動で破棄する必要はありません。 たとえば、アクティビティサブコンポーネントはAndroidInjection.inject()



呼び出し時に作成され、アクティビティが破棄されるまで存続します。







動的パラメータ



dagger-androidを使用すると、サブコンポーネントをビルドする必要がなくなり、 AndroidInjection.inject()



1回の呼び出しで依存関係の要求が達成されます。 疑問が生じるかもしれません。どうすればこのようなことができますか:







 long userId = getArguments().getLong(USER_ID); getAppComponent() .plusUserComponent(new UserModule(userId)) .inject(this);
      
      





userIdは、モジュールの動的パラメーターです。 たとえば、このパラメーターを使用してUserPresenter(UserRepository userRepository, Long userId)



を作成できます。







実装オプション:







オプション1:

使用されるオブジェクトにパラメーターを設定します。







 public class UserPresenter { private UserView userView; private UserRepository userRepository; private long userId; @Inject public UserPresenter(UserView userView, UserRepository userRepository) { this.userView = userView; this.userRepository = userRepository; } public void setUserId(long userId) { this.userId = userId; } } public class UserFragment extends BaseFragment implements UserView { @Inject UserPresenter userPresenter; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); userId = getArguments().getLong(USER_ID); userPresenter.setUserId(userId); } }
      
      





このオプションは、不変クラスには適していません。







オプション2:







作成時に動的パラメーターを受け入れないようにクラス自体を再構築し、メソッドを通じてパラメーター自体を使用します。







 public final class UserPresenter { private final UserView userView; private final UserRepository userRepository; @Inject public UserPresenter(final UserView userView, final UserRepository userRepository) { this.userView = userView; this.userRepository = userRepository; } public void loadUserInfo(long userId) { // } } public class UserFragment extends BaseFragment implements UserView { @Inject UserPresenter userPresenter; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); userId = getArguments().getLong(USER_ID); userPresenter.loadUserInfo(userId); } }
      
      





オプション3:







ファクトリーを使用して、動的パラメーターを持つオブジェクトの作成を実装します。







 public final class UserPresenter { private final UserView userView; private final UserRepository userRepository; private final long userId; public UserPresenter(final UserView userView, final UserRepository userRepository, long userId) { this.userView = userView; this.userRepository = userRepository; this.userId = userId; } } public final class UserPresenterFactory { private final UserView userView; private final UserRepository userRepository; @Inject public UserPresenterFactory(UserView userView, UserRepository userRepository) { this.userView = userView; this.userRepository = userRepository; } public UserPresenter create(long userId) { return new UserPresenter(userView, userRepository, userId); } } public class UserFragment extends BaseFragment implements UserView { @Inject UserPresenterFactory userPresenterFactory; UserPresenter userPresenter; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); userId = getArguments().getLong(USER_ID); userPresenter = userPresenterFactory.create(userId); } }
      
      





このようなファクトリーの作成は便利ではないか、時間がかかります。この問題を解決するには、 AutoFactoryを参照してください







RxJavaを使用する人により適したFernando Cejasのソリューションもあります。

ユースケースの動的パラメーター







おわりに



Dagger-androidを使用すると、Androidの基本コンポーネント( activity, fragment, service



など)の依存関係をより便利な方法で提供でき、サブコンポーネントを作成して制御する必要がなくなります。 アクティビティ、フラグメント、サービスなど より「きれい」に見えます。







この記事がdagger-androidの機能の理解に役立つことを願っています。








All Articles