Dagger2快速上手系列二

學習札記:Dagger2快速上手系列一
學習札記:Dagger2快速上手系列二

上文我們簡單的介紹了Dagger2的的快速使用,
這篇文章來說一說Dagger2的一些坑和注意事項。

1.@Named註解的使用
Dagger2中用@Name來依賴注入的對象做限定,這句話是什麼意思呢,也就是說比如我們在上文的例子中,我們通過依賴注入返回SUserManager對象,如果此時我們需要返回兩個不同這個對象,我們在SUserModule返回的只有一個,這個時候我們在依賴注入的地方和Module的工廠方法中加入同樣的這個Name註解,就可以區分返回不同的對象了。Named這個註解本身是可以有參數,也可以通過自定義註解用Qualifier來註解這個自定義註解,因爲Named這個註解就是用Qualifier這個註解的註解,下面通過代碼看一看.

容器中的代碼:

public class MainActivity extends AppCompatActivity {


    @Named("release")
    @Inject
    SUserManager daggerUserManager;
    @Named("debug")
    @Inject
    SUserManager daggerUserManagerDebug;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

       DaggerSUserComponent.create().inject(this);
  
        daggerUserManager.register();
    }
}

工廠中的代碼


public class SUserModule{

  @Provides
    public SUserStore provideSuserStrore() {
        return new SUserStore ();
    }
    @Provides
    public SApiService provideApiService() {
        return new SApiService();
    }

    @Named("release")
    @Provides
    public SUserManager provideUserManager(SApiService apiService, SUserStore userStore) {

        return new SUserManager(apiService, userStore);

    }
   	@Named("debug")
    @Provides
    public SUserManager provideUserManagerForDebug(SApiService apiService, SUserStore userStore) {

        return new SUserManager(apiService, userStore);

    }
}

2.作用域的坑

舉個簡單的例子,比如我們在網絡請求的時候,假設我們用到了一個OkHttpClient,我們在創建了一個新的Module,並提供了提供了一個實例,然後在需要注入的時候 用@Inject就可以使用了:

@Module
public class SUserModule{

	/*...
	省略其他代碼
	...*/
    @Singleton
    @Provides
    public OkHttpClient provideOkHttoClinet(){

       return new OkHttpClient.Builder().build();
    }
}

這樣咋一看沒有什麼問題,但是我們每次用到這個得時候,都會重新創建一遍OkHttpClient,這樣就造成了性能的消耗,這個時候Dagger2爲我們增加了一個 @Singleton來表明這個OkHttpClient是個單例,但是實際上,他只是做容器內的單例,也就是我們在MainActivity中使用OkHttpClient時,他是個單例,在另外的Activity中,比如登錄的Acvitity,它又重新被創建了,那怎麼辦才能做到唯一呢,因爲@Singleton是依附於Component的,一般的情況下,我們會寫個App的Component,在Application的初始化中去注入進去。讓其他的Component去依賴這個AppComponent,下面請看下代碼,
我們在AppComponent中提供獲取單例的OkHttpClient的聲明。

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
 OkHttpClient okHttoClinet();
}

我們在AppModule中實例化OkHttpClent,這個時候SUserModule裏面的OkHttpClient就可以去掉了。

@Module
public class AppModule {
    @Singleton
    @Provides
    public OkHttpClient provideOkHttpClient(){
        return new OkHttpClient();
    }
}

我們在Application中初始化AppComponent


public class MyApplication exntends Application{

		private AppComponent appComponent;

		public AppComponent getAppComponent(){
			return appComponent;
		}
		 @Override
		protected onCreate(){
			super.onCreate();
			appComponent=DaggerAppComponent().create();
		}
}

我們讓其他Component依賴於AppComponent,需要注意的是.由於AppComponent已經用了@Singleton這個註解來註解AppComponent了,所以在SUserComponent中需要用一個自定義scope來註解當前的Component,即有dependencies關係的組件之間的scope是不能相同的。

@ActivityScope
@Component(modules = {SUserModule.class,dependencies=AppComponent.class})
public interface SUserComponent {

    void inject(MainActivity activity);
}


自定義的scope


package com.android.seven.dagger2.dagger;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;

import javax.inject.Scope;
import javax.inject.Singleton;

import static java.lang.annotation.RetentionPolicy.RUNTIME;


@Scope
@Documented
@Retention(RUNTIME)
public @interface ActivityScope {
}

3,其他需要注意的地方
a.Component中需要inject的地方不能使用父類替換子類作爲參數,這個是註解迷失的坑。舉個例子比如在SUerComponent中的inject(MainActivity activity);這個方法中MainActivity不能用器父類替換,只能是MainActivity;
b.Component關聯的modules中不能有重複的provides,也就是關聯的多個module不能提供相同的對象;
b.module中provide,如果使用了scope,則component必須與其一致,比如AppComponent,如果module中provide沒有使用scope,則component無所謂,如果說component有dependencies關係,scope必須不一樣,即有依賴關係的component不一樣;
c.Sigleton的component不能依賴其他組件;
d.沒有scope的component不能依賴有scope的component;
e.一個component不能有多個scope(subComponent除外)
f.sigleton的生命週期依附於component。

暫時只整理這麼多,本文如果有不正之處,煩請之處,感謝感謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章