欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android依賴(lài)注入框架Dagger2的使用方法

 更新時(shí)間:2023年05月08日 11:08:29   作者:Tai_Monster  
Dagger2是一款基于Java的依賴(lài)注入框架,可以幫助Android開(kāi)發(fā)者管理和組織應(yīng)用的依賴(lài)關(guān)系。通過(guò)使用注解和代碼生成技術(shù),可以實(shí)現(xiàn)自動(dòng)化的依賴(lài)注入,減少手動(dòng)編寫(xiě)代碼的工作量

Dagger2注入框架原理簡(jiǎn)要分析

使用Dagger2需要的依賴(lài):

implementation 'com.google.dagger:dagger-android:2.46'
implementation 'com.google.dagger:dagger-android-support:2.46'
annotationProcessor 'com.google.dagger:dagger-android-processor:2.46'
annotationProcessor 'com.google.dagger:dagger-compiler:2.46'

示例代碼

這里先給出我的示例代碼,github上的demo點(diǎn)這里??

MainActivity

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    @Inject
    Gson gson;
    @Inject
    Gson gson2;
    @Inject
    SwordMan swordMan;
    //@Inject
    //Car car;
    ActivityMainBinding myBinding;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        myBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        App.get(MainActivity.this).getActivityComponent().inject(this);
        onClick();
        if(gson.hashCode() == gson2.hashCode()){
            Toast.makeText(this, "Same", Toast.LENGTH_SHORT).show();
        }else{
            Toast.makeText(this, "Different", Toast.LENGTH_SHORT).show();
        }
        myBinding.btTest2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this, swordMan.fighting(), Toast.LENGTH_SHORT).show();
            }
        });
    }
    private void onClick(){
        myBinding.btTest1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this,SecondActivity.class);
                startActivity(intent);
            }
        });
    }
}

SecondActivity

public class SecondActivity extends AppCompatActivity {
    ActivitySecondBinding S_Binding;
    @Inject
    Lazy<SwordMan> swordManLazy;//實(shí)現(xiàn)懶加載
    SwordMan swordMan = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        S_Binding = DataBindingUtil.setContentView(this,R.layout.activity_second);
        App.get(SecondActivity.this).getActivityComponent().inject(this);
        if(swordMan == null){
            Toast.makeText(this, "暫未初始化", Toast.LENGTH_SHORT).show();
        }
        swordMan = swordManLazy.get();
        //setContentView(R.layout.activity_second);
        S_Binding.button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(SecondActivity.this, swordMan.fighting(), Toast.LENGTH_SHORT).show();
            }
        });
    }
}

App

注意App類(lèi)需要在manifest清單文件中聲明。

public class App extends Application {
    ActivityComponent activityComponent;
    @Override
    public void onCreate() {
        super.onCreate();
        activityComponent = 
        DaggerActivityComponent.builder().swordmanComponent(DaggerSwordmanComponent.builder().build())
                .build();
    }
    public static App get(Context context){
        return (App) context.getApplicationContext();
    }
    ActivityComponent getActivityComponent(){
        return activityComponent;
    }
}

Component類(lèi)

@ApplicationScope
@Component(modules = GsonModule.class,dependencies = SwordmanComponent.class)
public interface ActivityComponent {
    void inject(MainActivity activity);
    void inject(SecondActivity activity);
}
@Component(modules = SwordmanModule.class)
public interface SwordmanComponent {
    SwordMan getSwordman();
}

Module類(lèi)以及實(shí)體類(lèi)

@Module
public class GsonModule {
    @ApplicationScope
    @Provides
    public Gson provideGson(){
        return new Gson();
    }
}
@Module
public class SwordmanModule {
    @Provides
    public SwordMan provideSwordman(){
        return new SwordMan();
    }
}
public class SwordMan {
    @Inject
    public SwordMan(){
    }
    public String fighting(){
        return "欲為大樹(shù),莫于草爭(zhēng)";
    }
}

生成代碼分析

Dagger2是通過(guò)注解生成中間類(lèi)的方式幫我們注入依賴(lài)的,我們就來(lái)分析它生成的中間類(lèi)的代碼。

由于注入器是在App類(lèi)中初始化的,所以我們先從App類(lèi)開(kāi)始看,App類(lèi)中最重要的無(wú)非就是這一句:

activityComponent = 
   DaggerActivityComponent.builder().swordmanComponent(DaggerSwordmanComponent.builder().build())
                .build();

通過(guò)DaggerActivityComonent以及builder的配置生成了一個(gè)注入器接口的實(shí)現(xiàn)類(lèi),所以我們先看DaggerActivityComponent類(lèi)

DaggerActivityComponent類(lèi)

public final class DaggerActivityComponent {
  private DaggerActivityComponent() {
  }
  public static Builder builder() {
    return new Builder();
  }
  public static final class Builder {
    private GsonModule gsonModule;
    private SwordmanComponent swordmanComponent;
    private Builder() {
    }
    public Builder gsonModule(GsonModule gsonModule) {
      this.gsonModule = Preconditions.checkNotNull(gsonModule);
      return this;
    }
    public Builder swordmanComponent(SwordmanComponent swordmanComponent) {
      this.swordmanComponent = Preconditions.checkNotNull(swordmanComponent);
      return this;
    }
    public ActivityComponent build() {
      if (gsonModule == null) {
        this.gsonModule = new GsonModule();
      }
      Preconditions.checkBuilderRequirement(swordmanComponent, SwordmanComponent.class);
      return new ActivityComponentImpl(gsonModule, swordmanComponent);
    }
  }
  private static final class ActivityComponentImpl implements ActivityComponent {
    	...
    }
}

我們先來(lái)看前面有關(guān)Builder的方法,由于我們?cè)贏ctivity的Component注解中添加了modules和dependencies的值,所以在builder中就會(huì)生成響應(yīng)的gsonModule(GsonModule gsonModule)和swordmanComponent(SwordmanComponent swordmanComponent)方法,這兩個(gè)方法分別是用來(lái)設(shè)置生成的注入器中的gsonModule和swordmanComponent對(duì)象的。

通過(guò)App類(lèi)中的調(diào)用的代碼我們可以發(fā)現(xiàn),對(duì)于注解中的modules,我們?cè)趧?chuàng)建注入器的時(shí)候是不需要手動(dòng)添加的,但是對(duì)dependencies注解來(lái)說(shuō)就需要手動(dòng)添加:

DaggerActivityComponent.builder().swordmanComponent(DaggerSwordmanComponent.builder().build())
                .build();//手動(dòng)添加了DaggerSwordmanComponent的注入器

builder中的Preconditions.checkNotNull()只是用來(lái)判空的,總的來(lái)說(shuō),builder這個(gè)內(nèi)部類(lèi)就是用來(lái)幫助構(gòu)建注入器實(shí)例的。所以我們接下來(lái)就來(lái)看這個(gè)注入器實(shí)例:

  private static final class ActivityComponentImpl implements ActivityComponent {
    private final SwordmanComponent swordmanComponent;
    private final ActivityComponentImpl activityComponentImpl = this;
    private Provider<Gson> provideGsonProvider;
    private Provider<SwordMan> getSwordmanProvider;
    private ActivityComponentImpl(GsonModule gsonModuleParam,
        SwordmanComponent swordmanComponentParam) {
      this.swordmanComponent = swordmanComponentParam;
      initialize(gsonModuleParam, swordmanComponentParam);
    }
    @SuppressWarnings("unchecked")
    private void initialize(final GsonModule gsonModuleParam,
       final SwordmanComponent swordmanComponentParam) {
      this.provideGsonProvider = DoubleCheck.provider(GsonModule_ProvideGsonFactory.create(gsonModuleParam));
      this.getSwordmanProvider = new GetSwordmanProvider(swordmanComponentParam);
    }
    @Override
    public void inject(MainActivity activity) {
      injectMainActivity(activity);
    }
    @Override
    public void inject(SecondActivity activity) {
      injectSecondActivity(activity);
    }
    private MainActivity injectMainActivity(MainActivity instance) {
		...
    }
    private SecondActivity injectSecondActivity(SecondActivity instance) {
      	...
    }
    private static final class GetSwordmanProvider implements Provider<SwordMan> {
      ...
    }
  }

先不看最后一個(gè)內(nèi)部類(lèi),先看注入器類(lèi)ActivityComponentImpl 實(shí)現(xiàn)了 ActivityComponent 接口,也就是說(shuō)它就是實(shí)際的注入器類(lèi),這個(gè)類(lèi)的構(gòu)造方法是私有的,說(shuō)明只能通過(guò)構(gòu)造器來(lái)構(gòu)造實(shí)例。先關(guān)注它的構(gòu)造方法,構(gòu)造方法傳入的參數(shù)正是我們?cè)贑omponent接口的注解中寫(xiě)入的值:

@Component(modules = GsonModule.class,dependencies = SwordmanComponent.class)
...
private void initialize(final GsonModule gsonModuleParam,
       final SwordmanComponent swordmanComponentParam){
       ...
       }

傳入了一個(gè)GsonModule和一個(gè)SwordmanComponent,和目前這個(gè)ActivityComponent類(lèi)似,這個(gè)SwordmanComponent肯定也是有一個(gè)實(shí)現(xiàn)類(lèi)的,我們后面再看這兩個(gè)類(lèi)的具體內(nèi)容。

接著我們接續(xù)看它的注入依賴(lài)的方法,我們?cè)谧⑷胍蕾?lài)時(shí),顯然是用到了inject方法,對(duì)應(yīng)不同的注入對(duì)象,將會(huì)調(diào)用不同的inject的重載方法,我們先看MainActivity的注入方法:

private MainActivity injectMainActivity(MainActivity instance) {
      MainActivity_MembersInjector.injectGson(instance, provideGsonProvider.get());
      MainActivity_MembersInjector.injectGson2(instance, provideGsonProvider.get());
      MainActivity_MembersInjector.injectSwordMan(instance, Preconditions.checkNotNullFromComponent(swordmanComponent.getSwordman()));
      return instance;
    }

injectMainActivity中分別調(diào)用了注入的方法,很顯然,就是將我們?cè)贛ainActivity中標(biāo)記為需要注入的變量給注入?yún)?shù),我們接下來(lái)看這個(gè)MainActivity_MembersInjector中間類(lèi)。

MainActivity_MembersInjector

就這個(gè)類(lèi)的命名來(lái)說(shuō),它應(yīng)該是具體負(fù)責(zé)成員變量注入依賴(lài)的注入器。前面說(shuō)到在ActivityComponentImpl調(diào)用了它的injectGson等方法,我們來(lái)看這三個(gè)方法:

@InjectedFieldSignature("com.example.dagger2demo.activitys.MainActivity.gson")
  public static void injectGson(MainActivity instance, Gson gson) {
    instance.gson = gson;
  }
  @InjectedFieldSignature("com.example.dagger2demo.activitys.MainActivity.gson2")
  public static void injectGson2(MainActivity instance, Gson gson2) {
    instance.gson2 = gson2;
  }
  @InjectedFieldSignature("com.example.dagger2demo.activitys.MainActivity.swordMan")
  public static void injectSwordMan(MainActivity instance, SwordMan swordMan) {
    instance.swordMan = swordMan;
  }

看到這里,這三個(gè)方法的作用已經(jīng)非常明顯了,將我們需要注入依賴(lài)的對(duì)象傳入這三個(gè)方法中,方法就會(huì)給需要注入依賴(lài)對(duì)象中標(biāo)記為@Inject的成員變量賦值。至于這個(gè)@InjectedFieldSignature注解,@InjectedFieldSignature注解是Dagger中的一個(gè)自定義注解,用于幫助Dagger在運(yùn)行時(shí)自動(dòng)生成代碼以實(shí)現(xiàn)依賴(lài)注入。它用于標(biāo)記要進(jìn)行依賴(lài)注入的字段,并提供了一個(gè)字符串參數(shù),用于標(biāo)識(shí)該字段所依賴(lài)的對(duì)象的類(lèi)型。在運(yùn)行時(shí),Dagger會(huì)掃描這些注解并自動(dòng)生成相應(yīng)的代碼,以實(shí)現(xiàn)將依賴(lài)注入到被標(biāo)記的字段中。

何處真正產(chǎn)生了實(shí)際參數(shù)

這時(shí)候新的問(wèn)題產(chǎn)生了,這些被注入的參數(shù)是在哪里被初始化的呢,換句話說(shuō),injectGson()方法中的第二個(gè)參數(shù)gson是在哪里被開(kāi)辟空間的呢,答案就在之前的ActivityComponentImpl中:

 private MainActivity injectMainActivity(MainActivity instance) {
      MainActivity_MembersInjector.injectGson(instance, provideGsonProvider.get());
 		...
    }

從這里可以看出,這個(gè)實(shí)際被注入的參數(shù)是由provideGsonProvider的get方法提供的:

   @SuppressWarnings("unchecked")
    private void initialize(final GsonModule gsonModuleParam,
        final SwordmanComponent swordmanComponentParam) {
      this.provideGsonProvider = DoubleCheck.provider(GsonModule_ProvideGsonFactory.create(gsonModuleParam));
      this.getSwordmanProvider = new GetSwordmanProvider(swordmanComponentParam);
    }
	...
	public final class GsonModule_ProvideGsonFactory implements Factory<Gson> {
	  private final GsonModule module;
	  public GsonModule_ProvideGsonFactory(GsonModule module) {
	    this.module = module;
	  }
	  @Override
	  public Gson get() {
	    return provideGson(module);
	  }
	  public static GsonModule_ProvideGsonFactory create(GsonModule module) {
	    return new GsonModule_ProvideGsonFactory(module);
	  }
	  public static Gson provideGson(GsonModule instance) {
	    return Preconditions.checkNotNullFromProvides(instance.provideGson());
	  }
	}

這里DoubleCheck 是 Dagger2 中的一個(gè)工具類(lèi),用于確保依賴(lài)只被創(chuàng)建一次,具體來(lái)說(shuō),由于我們?cè)谧⑷肫鹘涌谥袠?biāo)記了被注入?yún)?shù)的作用域,所以會(huì)調(diào)用DoubleCheck方法。緊接著我們看GsonModule_ProvideGsonFactory,很顯然實(shí)現(xiàn)調(diào)用了create方法,但是create方法又是實(shí)際調(diào)用了GsonModule_ProvideGsonFactory的構(gòu)造方法,這里傳入了GsonModule類(lèi),還記得GsonModule類(lèi)嗎?正是我們自己寫(xiě)的實(shí)例提供者。

現(xiàn)在我們繼續(xù)返回到ActivityComponentImpl中,看這個(gè)GsonModule的實(shí)例在哪里,答案在builder中。我們先一個(gè)一個(gè)往前捋:

首先在initialize方法中調(diào)用了create:

this.provideGsonProvider = DoubleCheck.provider(GsonModule_ProvideGsonFactory.create(gsonModuleParam))

所以我們需要看initialize方法中傳入的GsonModule實(shí)例來(lái)自哪里,是來(lái)自ActivityComponentImpl的構(gòu)造方法中:

private ActivityComponentImpl(GsonModule gsonModuleParam,
        SwordmanComponent swordmanComponentParam) {
      this.swordmanComponent = swordmanComponentParam;
      initialize(gsonModuleParam, swordmanComponentParam);
    }

那這個(gè)構(gòu)造方法中的GsonModule來(lái)自哪里呢,之前我們提到過(guò),由于這個(gè)構(gòu)造方法是私有的,所以我們只能通過(guò)構(gòu)造器builder來(lái)創(chuàng)建,所以答案顯然是在builder這個(gè)內(nèi)部類(lèi)中:

    public ActivityComponent build() {
      if (gsonModule == null) {
        this.gsonModule = new GsonModule();
      }
      Preconditions.checkBuilderRequirement(swordmanComponent, SwordmanComponent.class);
      return new ActivityComponentImpl(gsonModule, swordmanComponent);
    }

這個(gè)GsonModule類(lèi)的實(shí)例正是調(diào)用了我們寫(xiě)的GsonModule的構(gòu)造方法,所以我們可以畫(huà)出傳遞的流程圖:

簡(jiǎn)要流程圖(僅適用于本示例)

簡(jiǎn)而言之,Dagger2正是通過(guò)APT和生成的中間件代碼來(lái)實(shí)現(xiàn)依賴(lài)注入的。

到此這篇關(guān)于Android依賴(lài)注入框架Dagger2的使用方法的文章就介紹到這了,更多相關(guān)Android Dagger2內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論