Android Dagger 2はゼロ単列(一)から基礎注釈

8377 ワード

転送は出典を明記してください.https://www.jianshu.com/p/7ee1a1100fabAndroid界で最も殺傷力のあるナイフとして、Dagger 2は、このシリーズの文章で最も通俗的な言語でその正体を明らかにします.  边缘OB:零単排から低分局から高分局まで、First BloodからHoly Shitまで、Rampage(暴走)は何も言わない! Android Dagger 2ゼロ単列(一)基礎注釈 Android Dagger 2ゼロ単列(二)@Qualifier Android Dagger 2ゼロ単列(三)@Scope Android Dagger 2ゼロ単列(四)DependenciesとSubComponent
1.Dagger 2の概要
  "A fast dependency injector for Android and Java."Dagger 2 GitHubアドレスのトップページの概要は、Androidとjavaの急速な依存注入という言葉です.簡単に述べると,コンポーネントは使用に依存し,依存の具体的な実装は容器に任せて決定することがDI(Dependency Injection)フレームワークの核心思想である.またDagger 2を使用すると性能の消耗を心配することなく,反射を使用せず,すべての注釈はコンパイル期間にとどまる.
2.Dagger 2の構成:
dependencies {
    api 'com.google.dagger:dagger:2.x'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.x'
}

  注意:gradleバージョンが2.2未満の場合、aptプラグインを使用する必要があります.Kotlinの書き方も少しあります.
3.注釈の分類:
注記の役割を説明する前に、dagger 2の最も簡単な例を見てみましょう.バスを探して駐車場に停めます(BusはParkingActivityに注入します)、駐車場はバスがどんなルートで駐車しても(ParkingActivityはBusがどのように注入しても)、駐車場のスケジューラは管理を担当します(Dagger 2容器はBusをParkingActivityに注入します).  DaggerParkingComponentクラスはコンパイル後にDagger 2が自動的に生成され、ParkingComponentの実装クラスであり、DaggerParkingComponentは実際の車場スケジューラであり、ParkingComponentは車場スケジューラに対する制約であり、onCreateメソッドで注入パスが完了したといえる.
public class Bus {
    @Inject
    public Bus() {
    }
}

public class ParkingActivity extends Activity {
    @Inject
    Bus mBus;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dagger);
        DaggerParkingComponent.create().inject(this);//DaggerParkingComponent         
        ((TextView) findViewById(R.id.text)).setText(mBus.toString());
    }
}

@Component
public interface ParkingComponent {
    void inject(ParkingActivity activity);
}

@Inject注記:  (1)注記この属性は注入に依存する必要があり、private修飾は使用できません.サンプルコードは属性mBus(Busの駐車スペース)を注入する必要があることを示します.
    @Inject
    Bus mBus;

  (2)注釈この方法は注入に依存する必要があり、抽象的な方法ではなくprivate修飾を使用することができず、サンプルコードは注入方法injectBusを必要とすることを示す.
    //@Inject
    Bus mBus;
    @Inject
    public void injectBus(Bus bus) {
        mBus = bus;
    }

  メソッド注入のパラメータは同様にDagger 2コンテナから提供され,以上のコードの目的は第1点で紹介した属性注入と同様にmBusを注入するためであり,目的が注入属性であればメソッド注入と属性注入はほとんど区別されず,属性注入はDagger 2で最も多く用いられる注入方式である.では、どのような場合に方法で注入すべきですか?たとえば、thisオブジェクトを必要とする場合、メソッド注入は安全なthisオブジェクトを提供することができる.  注意,Dagger 2コンテナは属性注入を呼び出してからメソッド注入を行い,サンプルコードmBusの@Injectを注釈解除すると,mBusは2回注入され,2回注入されたBusも異なる.  (3)注記構築方法では、Dagger 2に依存関係を提供することができることを示しています.Dagger 2は、この構築方法を使用してオブジェクト(Busの由来)を構築できます.
    @Inject
    public Bus() {
    }

  複数のコンストラクション関数がある場合は、1つしか注釈できません.そうしないと、コンパイルエラーが発生します.マルチコンストラクションメソッドの方法は次の編で紹介します.@Component注記:  は一般的にインタフェースを注記するために使用され、注記されたインタフェースはコンパイル時に対応するインスタンスを生成し、インスタンス名は一般的にDaggerを接頭辞とし、必要な注入依存(ParkingActivityのmBus属性)と提供依存(Busクラス構築方法)との橋渡しとして提供される依存(Bus)を必要な注入依存(ParkingActivityのmBus属性)に注入する.一般的にはDagger 2の容器で、例では車場スケジューラで、バスと駐車場を結びつけています.駐車場のスケジューラは駐車場にバスを用意しなければならないことを知っています.駐車場は車がどこから来たのかを知る必要はありません.どうやって止めるのかを知る必要もありません.駐車場のスケジューラは車を探してから、駐車スペースに停めれば終わります.リーダーの車を待っていればいいです.  の例をまとめると,2つの@Inject注釈が依存関係を形成し,@Componentがこの関係を結ぶ橋渡しとして存在し,依存を見つけて注入し,注入と被注入との間に干渉せず,@ComponentをコンパイルしてDaggerをプレフィックスとするインスタンスを生成し,インスタンスのメソッド注入を呼び出す.
例2、指導者は不適切だと思って、自分でバスを運転したことがないので、保険のために急いで秘密に言いつけて、バスの運転手に渡して、秘密は自然に車場のスケジューラに言った.車場のスケジューラは考えてみると、前より1つのステップを増やしてバスに運転手を配置しただけだ(Bus類にStringタイプDriverの構造方法を追加).そこでバスを運転している隣の王さんに電話したら、王さんは自然に約束したので、例1のコードを修正しました.
public class Bus {
    private String driver;
    @Inject
    public Bus(String driver) {
        this.driver = driver;
    }
}

public class ParkingActivity extends Activity {
    @Inject
    Bus mBus;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dagger);
        DaggerParkingComponent.create().inject(this);//DaggerParkingComponent         
        ((TextView) findViewById(R.id.text)).setText(mBus.toString());//  Bus toString()        "    ",    
    }
}

@Component(modules = ParkingModule.class)
public interface ParkingComponent {
    void inject(ParkingActivity activity);
}

@Module
public class ParkingModule {
    public ParkingModule() {
    }
    @Provides
    public String provideDriver() {
        return "    ";
    }
}

@Module注記:  この注記は@Providesと結合してDagger 2に依存関係を提供し、上記@Injectの3点目の補足は、@Injectで依存を提供できない場所、例えばサードパーティライブラリで提供されたクラス、基本データ型などソースコードを変更できない場合に使用します.@Provides注記:  @Providesはメソッドのみを注記でき、メソッドのクラスに@Module注記が必要です.注記後のメソッドは、Dagger 2がメソッドインスタンスオブジェクトで依存を提供できることを示します.慣例に従って,@Providesメソッドのネーミングはprovideを接頭辞とし,読み取り管理が容易である.  例2まとめでは、まず@Component注記には、Dagger 2がParkingModuleクラスから依存を検索できることを示すParkingModuleクラスが含まれています.Dagger 2は、@Provides注釈のメソッドインスタンス依存を自動的に検索し、最後に注入 注意1を完了します.ParkingModuleにもBus依存が提供されると、Dagger 2は@Module注記のクラスで依存を優先的に検索します.ない場合はクラスの@Injectの構造方法を調べます.次のコードのように、Busの運転手は王さんではなく王さんです.
@Module
public class ParkingModule {
    public ParkingModule() {
    }
    @Provides
    public String provideDriver() {
        return "    ";
    }
    @Provides
    public Bus provideBus() {
        return new Bus("    ");
    }
}

  注意2,@Moduleクラスは構築メソッドから依存を伝達し,@Providesメソッドにも依存関係を持つことができる.  @Providesメソッドにも依存関係がある場合、Dagger 2は、再帰的な状態と同様に依存を提供するメソッドを検索し続け、インスタンスを一歩一歩返します.次のコードでは、ParkingModule構築メソッドはdriverに転送され、provideDriverメソッドに依存戻りを提供し、provideDriverはdriverをprovideBusメソッドの依存インスタンスBusとして返す.ParkingModuleにパラメトリック構造方法を加えると、呼び出し方法も変えなければなりません.今では運転手は階下の李さんになりました.
@Module
public class ParkingModule {
    private String driver;
    public ParkingModule(String driver) {
        this.driver = driver;
    }
    @Provides
    public String provideDriver() {
        return driver;
    }
    @Provides
    public Bus provideBus(String driver) {
        return new Bus(driver);
    }
}
    //      
    DaggerParkingComponent.builder().parkingModule(new ParkingModule("    ")).build().inject(this);

注入方法についての疑問:Dagger 2に初めて触れると、Buildのたびにcreate()メソッドがなくなることがありますが、実はcreate()メソッドは注入プロセスを簡素化して設計されており、ソースコードをクリックすると実際に内部で呼び出されています.
  public static MainComponent create() {
    return new Builder().build();
  }

以下の場合、create()メソッドが生成されます.  (1)@Component注釈インタフェースはModuleを宣言していません.この場合は言うまでもありません.  (2)@Component注記インタフェースはModuleを宣言しており、Moduleを使用して提供された依存性はありません.Moduleの構築方法にパラメータがあるかどうかにかかわらず、@Component注記で生成されたJavaファイルにもヒントがあります.
    /**          Module, component         ,  Module        。
     * @deprecated This module is declared, but an instance is not used in the component. This
     *     method is a no-op. For more, see https://google.github.io/dagger/unused-modules.
     */

  (3)@Component注記インタフェースはModuleを宣言し、Moduleが提供する依存を使用し、Moduleの構造方法にはパラメータがなく、ポイントを入れるとソースコードが実際に内部でModuleを初期化している.
    public MainComponent build() {
      if (mainModule == null) {
        this.mainModule = new MainModule();
      }
      return new DaggerMainComponent(this);
    }

以下にcreate()メソッドは必ず表示されません.  (1)@Component注記インタフェースはModuleを宣言し、Moduleが提供する依存を使用し、Module構築メソッドにはパラメータがあります.このパラメータを依存として使用するかどうかにかかわらず、注入はModuleを初期化して注入に成功する必要があります.ソースコードを見て、Moduleを初期化しないと、直接異常が報告されます.
    public MainComponent build() {
      if (mainModule == null) {
        throw new IllegalStateException(MainModule.class.getCanonicalName() + " must be set");
      }
      return new DaggerMainComponent(this);
    }

  接触開始時のcreate()メソッドは、例えばModuleが宣言されており、Module構築メソッドにはパラメータがあり、create()メソッドがあれば、このときModuleが提供する依存性が使用されていないことを示し、Moduleで原因を検索することができる検出手段として使用することができる.実際のプロジェクト運用では,create()メソッドは比較的少なく,一般的にModuleが参照される.
最後に依存注入プロセスをまとめた:1:Moduleにそのインスタンスがあるかどうかを調べる@Providesメソッド.  1.1:はい、2点目を行きます.  1.2:いいえ、このインスタンスに@Inject構築メソッドがあるかどうかを検索します.    1.1.1:はい、3点目を行きます.    1.1.2:いいえ、注入に失敗しました.2:@Providesメソッドにパラメータ  2.1:あるかどうかは、1番目のポイントに戻って各パラメータの依存 2.2:いいえ、インスタンスこのクラスは1回の依存を返します3:@Inject構築メソッドにパラメータ 3.1:あるかどうかは、1番目のポイントに戻って各パラメータの依存 3.2:いいえ、インスタンスこのクラスは1回の依存を返します4:以上のプロセスは注入ターゲットのすべての依存を返し、最後に注入に依存します.
  DemoソースカットdaggerOneパケット名 Dagger 2 GitHubアドレス Dagger 2公式サイトアドレス すべてのテストインスタンスは2.15バージョンに基づいています.次の記事では、複数の@Providesメソッドと同じデータ型を返すマルチコンストラクションメソッドを検討します:@Qualifier注記.