前の記事で 、特別な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
メソッドがあります。 渡されたタイプに応じて、次のインターフェースのいずれかの実装を検索します。
- HasActivityInjector
- HasFragmentInjector
- HasServiceInjector
- HasContentProviderInjector
- HasBroadcastReceiverInjector
短剣アンドロイドサポート
- HasSupportFragmentInjector
目的のAndroidInject
を含む目的のインターフェイスの実装の検索は、ライフタイムが長いオブジェクトで行われます。
HasActivityInjector, HasServiceInjector, HasContentProviderInjector, HasBroadcastReceiverInjector
各インターフェイスをアプリケーションに実装する必要があります。 HasFragmentInjector
またはHasSupportFragmentInjector
は、フラグメントまたはアクティビティまたはapplication
に実装application
。実装は、親フラグメント、このフラグメントが配置されているアクティビティ、およびapplication
順序で検索されapplication
。
AndroidInjection.inject()
は、スーパーメソッドを呼び出す前に、特定のメソッドで呼び出す必要があります。
- アクティビティ-onCreate
- フラグメント-onAttach
- サービス-onCreate
- IntentService-onCreate
- ContentProvider-onCreate
- BroadcastReceiver-onReceive
Dagger-androidには使用できるクラスがあります(これらのクラスは既に必要なインターフェイスを実装し、 AndroidInjection.inject()
メソッドを呼び出しています):
- DaggerApplication( HasActivityInjector、HasFragmentInjector、HasServiceInjector、HasBroadcastReceiverInjector、HasContentProviderInjector )
- DaggerActivity( HasFragmentInjector )
- DaggerFragment( HasFragmentInjector )
- DaggerBroadcastReceiver
- DaggerContentProvider
- DaggerService
- DaggerIntentService
短剣アンドロイドサポート
- DaggerApplication( DaggerApplication + HasSupportFragmentInjectorと同じ)
- DaggerAppCompatActivity( HasFragmentInjector、HasSupportFragmentInjector )
- DaggerFragment( HasSupportFragmentInjector )。
何らかの理由でこれらのクラスのいずれかを拡張できない場合、必要なインターフェイスをいつでも実装できます。
短剣クラスの使用例:
メインコンポーネントを定義します。
コンポーネントが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);
IntentServiceを使用した例
public class MyIntentService extends DaggerIntentService { @Inject UserRepository userRepository; public MyIntentService() { super("MyIntentService"); } @Override protected void onHandleIntent(@Nullable Intent intent) {
受信機の例
public class SomeReceiver extends DaggerBroadcastReceiver { @Inject UserRepository userRepository; @Override public void onReceive(Context context, Intent intent) { super.onReceive(context, intent);
コンポーネントのライフサイクル
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) {
オプション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の機能の理解に役立つことを願っています。