Dagger2的使用總結

Dagger是一個完全靜態的,在編譯時進行依賴注入的框架,原來是由Square公司維護的然後現在把這堆東西扔給Google維護了。Dagger解決了基於反射帶來的開發和性能上的問題(因爲Dagger並沒有用反射來做依賴注入)說了那麼多,其實就是告訴我們這傢伙可以用來做依賴注入哦。

依賴注入:我們在做項目時,經常需要在一個對象裏去創建另一個對象的實例,這種行爲是產生耦合的常見形式,對於一個大型項目來說,過多的相互依賴會導致代碼難以維護,很容易就會碰到修改一個小需求需要大面積的修改各種代碼,特別是代碼原來不是自己維護的,擼着代碼的你就開始問候別人家的親友了。

在需要依賴的類中不要通過new來創建依賴而是通過方法提供的參數注入進來,這樣我們的需要依賴的類和提供依賴的類的實現方法分隔開了,一切又變得如此美好咯。

dagger2是一個依賴注入框架,在編譯期間自動生成代碼,負責依賴對象的創建

用dagger2提供依賴有什麼好處:爲了進一步解耦和方便測試,我們會使用依賴注入的方式構建對象 (不使用 new 來創建依賴對象)。在mvp中,presenter層會持有view和model層的依賴,依賴注入主要用於解耦通過依賴注入創建對象,不再使用new來創建對象。

依賴注入的目的是:給你提供一個對象依賴。


Dagger2的常用註解: 
@Inject:此註解用於告訴Dagger2,我們需要這個類的實例對象。主要用於標記哪個類是需要注入的。
@Module:此註解裏面全是方法,用於對外提供對象,自己定義方法,方法上使用@Provides。自定義一個類,以Module結尾,用@Module註解。
@Provides:此註解用於標記方法,表示可以通過這個方法獲取一個對象,一般用於自定義類中。
@Component:此註解主要用於關聯自定義module類和MainActivity;關聯module使用:@Component(modules={UserModule.class});關聯Activity,以方法參數的形式傳入MainActivity到連接器中

@Named與@Qualifier:用於區別不同對象的實例。必須要成對出現,否則會報錯。

@PerActivity:限定對象的生命週期和Activity一樣。一般應用於自定義的Component上。

@Singleton:標記爲單例模式,如果在自定義Module中使用了此註解,在自定義的Component上也要使用該註解。


使用方式:

1)自定義Module,裏面的方法用於提供依賴,

2)自定義Component接口,裏面全是Activity的注入方法,

3)按Ctrl+F9進行編譯。


自定義Module類:

自定義module中的方法 要以provide開頭

通過構造方法傳遞Context

 

如果定義的module,需要傳參數,就需要在Activity使用build進行諸如



添加依賴:

    //添加依賴
    compile 'com.google.dagger:dagger:2.9'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.9'

MainActivity代碼:此依賴注入的目的是獲取ApiService類的實例,然後調用其中的register方法;編譯後會自動生成DaggerUserComponent類

package com.example.administrator.testdragger2.old;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.example.administrator.testdragger2.R;
import javax.inject.Inject;

public class MainActivity extends AppCompatActivity {
    
    @Inject
    ApiService apiService;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        //Dagger會自動創建這個類,以Dagger開頭+UserComponent
        DaggerUserComponent.create().inject(this);
        apiService.register();
        
    }
}
UserComponent代碼:自定義接口

package com.example.administrator.testdragger2.old;

import dagger.*;

/**
 * Created on 2017/5/8.
 * Author:crs
 * Description: UserComponent連接器,橋樑
 */
@Component(modules = {UserModule.class})
public interface UserComponent {
    //當前只能寫MainActivity,不能寫Activity,要不然會出現空指針。
    void inject(MainActivity activity);
}
UserModule代碼:自定義module類,主要用於提供依賴

package com.example.administrator.testdragger2.old;

import dagger.Module;
import dagger.Provides;

/**
 * Created on 2017/5/8.
 * Author:crs
 * Description:用於提供依賴
 */

@Module
public class UserModule {

    @Provides
    ApiService provideApiService(){
        return new ApiService();
    }
}
ApiService類:

package com.example.administrator.testdragger2.old;

import android.util.Log;

/**
 * Created on 2017/5/8.
 * Author:crs
 * Description:ApiService
 */
public class ApiService {

    private static final String TAG = "ApiService";

    public void register() {
        //請求網絡數據
        Log.i(TAG,"測試數據");

    }
}

———————————————————————————————————————>

如果自定義類module中的方法,需要一個對象參數,怎麼處理?需要一個方法去提供這個對象。

1)在類的構造方法上添加@Inject註解

2)自己寫一個方法去提供參數對象

package com.example.administrator.testdaggger2;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import javax.inject.Inject;

public class MainActivity extends AppCompatActivity {


    @Inject
    UserStore userStore;

    @Inject
    UserManager userManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        //主要兩個問題:
        //1)自定義Module需要傳遞上下文怎麼辦
        //2)自定義Module中的方法中需要參數對象怎麼處理?(構造函數、自己提供方法)

        //Dagger會自動創建這個類,以Dagger開頭+UserComponent,編譯時注入,按Ctrl+F9編輯即可
        //DaggerUserComponnent.create().inject(this);
        //userManager.register();

        //Dagger的關係非常簡單,MainActivity中需要對象,那麼就在Module中提供對象;而他們之間的橋樑就是componnent

        //自定義類Module的構造方法中需要傳入一個上下文對象,那麼在MainActivity中就需要傳遞進去。
        //使用下面的這種方式進行參數傳遞:this就是上下文
        DaggerUserComponnent.builder().userModule(new UserModule(this)).build().inject(this);
        userManager.register();

    }
}

package com.example.administrator.testdaggger2;

import android.content.Context;

import dagger.Module;
import dagger.Provides;

/**
 * Created on 2017/5/9.
 * Author:crs
 * Description:XXX
 */
@Module
public class UserModule {

    //在Module中傳遞上下文對象
    private Context mContext;
    public UserModule(Context context) {
        this.mContext = context;
    }
    @Provides
    UserStore provideUserStore(){
        return new UserStore();
    }

    //如果自定義Module中的方法需要對象參數,怎麼處理?
    //1)通過Module中的方法進行提供,比如provideUserStore()
    //2)通過類的構造函數進行提供對象,註釋掉上面的provideUserStore()方法
    //3)代碼執行順序:創建參數對象的方法先執行,比如構造;
    @Provides
    UserManager provideUserManager(UserStore userStore) {
        return new UserManager(userStore);
    }

}
package com.example.administrator.testdaggger2;

import android.util.Log;

import javax.inject.Inject;

/**
 * Created on 2017/5/9.
 * Author:crs
 * Description:UserStore 用戶數據存儲
 */
public class UserStore {
    //通過構造函數提供依賴
    @Inject
    public UserStore() {
    }

    private static final String TAG = "UserStore";

    public  void register(){
        Log.i(TAG,"測試數據");

    }
}

———————————————————————————————————————>

模塊化開發:自定義module之間相互include,component之間相互依賴

通過@Named @Qualifier:區別不同對象的實例

同一個類,可能要創建兩個對象,處理不同的業務邏輯
通過類型進行注入,根據@Inject標記的變量類型ApiService,在Module中尋找返回值爲ApiService的方法進行調用。但是如果Module中有多個方法,它們的返回值都爲ApiService,那麼就需要使用@Named註解用於區別。(區分不同對象的實例@Qualifier)
比如:訪問測試服務器,訪問正式服務器

代碼如下:

package com.example.administrator.testdragger2.dagger2;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import com.example.administrator.testdragger2.R;


import javax.inject.Inject;
import javax.inject.Named;

/**
 * Created on 2017/5/9.
 * Author:crs
 * Description:TestMainActivity
 */
public class TestMainActivity extends AppCompatActivity {
    
    private static final String TAG ="TestMainActivity" ;
    //訪問測試服務器
    @Named("dev")
    @Inject
    ApiService apiServiceDev;

    //訪問正式服務器
    @Named("release")
    @Inject
    ApiService apiServiceRelease;
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);

        DaggerUserComponent.builder().httpModule(new HttpModule()).userModule(new UserModule(this)).build().inject(this);
        //此時這兩個兩個對象的內存地址是不一樣的
        Log.i(TAG,apiServiceDev.toString());
        Log.i(TAG,apiServiceRelease.toString());

        //apiServiceDev.register();
        //apiServiceRelease.register();
    }
}

Component連接兩個Module(可以連接多個Module)

package com.example.administrator.testdragger2.dagger2;

import dagger.Component;

/**
 * Created on 2017/5/9.
 * Author:crs
 * Description:UserComponent
 */
@Component(modules={UserModule.class,HttpModule.class})
public interface UserComponent {
    void inject(TestMainActivity activity);
}
UserModule包含HttpModule

package com.example.administrator.testdragger2.dagger2;

import android.content.Context;

import javax.inject.Named;

import dagger.Module;
import dagger.Provides;
import okhttp3.OkHttpClient;

/**
 * Created on 2017/5/9.
 * Author:crs
 * Description:自定義Module類
 */
//表示當前module引用HttpModule,進而提供OkHttpClient的對象
@Module(includes = {HttpModule.class})
public class UserModule {

    private Context mContext;
    UserModule(Context context) {
        this.mContext=context;
    }

    //此時缺少OkHttpClient的實例,並且當前自定義Module中並沒有提供,如何處理?
    @Named("dev")
    @Provides
    ApiService provideApiServiceDev(OkHttpClient client){
        return new ApiService(client);
    }

    @Named("release")
    @Provides
    ApiService provideApiServiceRelease(OkHttpClient client){
        return new ApiService(client);
    }
}
package com.example.administrator.testdragger2.dagger2;

import java.io.IOException;

import javax.inject.Inject;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * Created on 2017/5/9.
 * Author:crs
 * Description:ApiService網絡請求
 */
public class ApiService {
    //常用類:OKHttpClient,Request,RequestBody,CallBack

    OkHttpClient client;

    //構造函數
    @Inject
    public ApiService(OkHttpClient client) {
        this.client=client;
    }


    //主要用於網絡請求
    public void register(){
        RequestBody body=RequestBody.create(null,"");
        Request request = new Request.Builder()
                .url("")
                .post(body)
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

            }
        });
    }
}
———————————————————————————————————————>

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