iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 12
1
Mobile Development

Android 開發經驗三十天系列 第 12

[Android 開發經驗三十天]D12一Dagger(上)

今日事,今日畢。完成鐵人文才算今日畢唷!Go~ /images/emoticon/emoticon06.gif

github傳送門:https://github.com/uuko/modulepra

安安,在昨天講完基礎DI知識之後,今天來介紹一下Dagger

/*

  • Component ->Module
  • Module -> provides
  • Inject
    */

Q:@Module作用?
提供的地方,主要標記要提供甚麼
標記用的Annoatation 為@Provides是用來標記function之類的
/Singleton 單例模式 在同一個component作用域下只有一個/
/Provides 提供依賴實例/

Q:@Named作用?

A:使用 @Named 標記 Module 中生成class實例的方法
如下面的@Named("UserApiUrl") 就是將他回傳的String命名為UserApiUrl
而當我們Retrofit需要url的時候在參數
Retrofit provideUserRetrofit(@Named("UserApiUrl") String url..
就能找到你提供的地方,讓他可以成功匹配到

創一個APIModule

@Module
public class APIModule {

@Provides
@Singleton
APIService provideUserApi(@Named("UserApi")Retrofit retrofit){
    return  retrofit.create(APIService.class);
}

@Provides
@Singleton
@Named("UserApi")
Retrofit provideUserRetrofit(@Named("UserApiUrl") String url,
                             @Named("UserApiClient") OkHttpClient okHttpClient){
    return new Retrofit.Builder()
            .baseUrl(url)
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build();
    //addCallAdapterFactory 是要支援有Observerable的
}

@Singleton
@Provides
@Named("UserApiUrl")
String provideUserApiUrl(){
    return "https://jsonplaceholder.typicode.com";

    //如果要getResource要context.get ...
}

@Singleton
@Provides
@Named("UserApiClient")
OkHttpClient provideUserOkhttpClient(HttpLoggingInterceptor httpLoggingInterceptor){
    return new OkHttpClient.Builder()
            .addInterceptor(httpLoggingInterceptor)
            .connectTimeout(20, TimeUnit.SECONDS)
            .readTimeout(20,TimeUnit.SECONDS)
            .writeTimeout(20,TimeUnit.SECONDS)
            .build();

}

//HttpLoggingInterceptor 有404 200 等連線狀態用的
    @Provides
    @Singleton
    public HttpLoggingInterceptor provideHttpLoggingInterceptor() {
        return new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY);
    }
}

APIService貼這邊

public interface APIService {
    @GET("/users")
    Observable<List<Users>> getUsers();
}

而我們要提供一個主要的(可要可不要),只是我習慣如果有整個Application共用就創一個Module跟一個Component裝進去

在裡面提供Application跟Context上下文,以便要用的時候可以用到

@Module
public class ApplicationModule {

    private Application mApplication;

    /*從全局 application拿到application*/
    public ApplicationModule(Application application){
        this.mApplication=application;
    }

    /*提供整個應用程序的上下文*/
    @Provides
    public Context provideContext(){
        return mApplication.getApplicationContext();
    }

    /*提供整個應用程序的application*/
    @Provides
    public Application provideApplication(){
        return mApplication;
    }

    /*提供Composiable 為了給別的Module使用*/
    @Provides
    public CompositeDisposable provideCompositeDisposable() {
        return new CompositeDisposable();
    }
}

Q:@Component作用?
A:為interface,在@Component中可以標記要引用那些module
而APIService跟CompositeDisposable都需要提供出去
也因為跟其他的component是依賴關係 所以提供給他們*

@Singleton
@Component(modules = {APIModule.class
                        ,ApplicationModule.class
                        ,SockettModule.class})
public interface ApplicationComponent {
    /*depency需求者可以呼叫*/
    void  inject(Application application);

    /*跟其他的component是依賴關係 所以提供給他們*/
    APIService getUserApi();

    CompositeDisposable getCompositediposable();


    /*如果有name的話一定要記得給*/
    @Named("APIServiceConnection")
    ApiSocketProvider apiSocketProviderConnect();




}

注:如果有Named的話一定要記得給才吃的到他在哪

前面有說到我習慣把如果所有都有提供的綁到Application
所以我們現在來自定義全局變量 Application

然後要綁定的話用
要用前面的inject綁定
DaggerApplicationComponent.builder(內建),在寫這之前要先build一下才能用
applicationComponent=DaggerApplicationComponent.builder()
.applicationModule(new ApplicationModule(this))
.aPIModule(new APIModule())
.sockettModule(new SockettModule())
.build();
applicationComponent.inject(this);

/*自定義全局變量 Application
* 要在manifest加上android:name=""
* */
public class Application extends android.app.Application {

    private ApplicationComponent applicationComponent;

    public static Application get(Context context)
    {
        return (Application)context.getApplicationContext();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        applicationComponent=DaggerApplicationComponent.builder()
                .applicationModule(new ApplicationModule(this))
                .aPIModule(new APIModule())
                .sockettModule(new SockettModule())
                .build();
        applicationComponent.inject(this);
    }
    public ApplicationComponent getApplicationComponent(){
        return applicationComponent;
    }
}

注:要在manifest加上android:name=""加上自定的Application


上一篇
[Android 開發經驗三十天+Spring Boot]#D11-DI (Dagger in Android / IOC in Spring Boot)前言
下一篇
[Android 開發經驗三十天]D13一Dagger(下)
系列文
Android 開發經驗三十天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言