亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android依賴注入框架Dagger2的使用方法

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

Dagger2注入框架原理簡要分析

使用Dagger2需要的依賴:

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點這里??

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;//實現(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類需要在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類

@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類以及實體類

@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 "欲為大樹,莫于草爭";
    }
}

生成代碼分析

Dagger2是通過注解生成中間類的方式幫我們注入依賴的,我們就來分析它生成的中間類的代碼。

由于注入器是在App類中初始化的,所以我們先從App類開始看,App類中最重要的無非就是這一句:

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

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

DaggerActivityComponent類

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 {
    	...
    }
}

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

通過App類中的調(diào)用的代碼我們可以發(fā)現(xiàn),對于注解中的modules,我們在創(chuàng)建注入器的時候是不需要手動添加的,但是對dependencies注解來說就需要手動添加:

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

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

  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> {
      ...
    }
  }

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

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

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

接著我們接續(xù)看它的注入依賴的方法,我們在注入依賴時,顯然是用到了inject方法,對應(yīng)不同的注入對象,將會調(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)用了注入的方法,很顯然,就是將我們在MainActivity中標記為需要注入的變量給注入?yún)?shù),我們接下來看這個MainActivity_MembersInjector中間類。

MainActivity_MembersInjector

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

@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;
  }

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

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

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

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

從這里可以看出,這個實際被注入的參數(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 中的一個工具類,用于確保依賴只被創(chuàng)建一次,具體來說,由于我們在注入器接口中標記了被注入?yún)?shù)的作用域,所以會調(diào)用DoubleCheck方法。緊接著我們看GsonModule_ProvideGsonFactory,很顯然實現(xiàn)調(diào)用了create方法,但是create方法又是實際調(diào)用了GsonModule_ProvideGsonFactory的構(gòu)造方法,這里傳入了GsonModule類,還記得GsonModule類嗎?正是我們自己寫的實例提供者。

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

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

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

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

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

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

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

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

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

簡而言之,Dagger2正是通過APT和生成的中間件代碼來實現(xiàn)依賴注入的。

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

相關(guān)文章

最新評論