Dagger-android 量身定做的Dagger

目錄

0. 爲什麼定製?

1. 2.10版本複雜的方式

1.0 導包

1.1 依賴創建

1.2 依賴注入

1.3 讓這一切被Dagger所知曉

1.4 源碼看了一下 結合 生成的代碼

2. 2.11版本@ContributesAndroidInjector


0. 爲什麼定製?

從 Dagger2入門 瞭解到,Dagger2的一個坑就是:

Component inject(container c) 容器必須傳入與你實際調用inject相同的類。也就是說不能c傳入BaseActivity,實際調用在XActivity。

也就是說如果我們用到了Dagger2,就必須每個Activity中去寫一句如下的inject(this),肯定是不可能這麼low的。

DaggerUserComponent.create().inject(this);

Dagger提供了兩種方式解決:

  • 2.10版本提供了相對複雜的解決方式
  • 2.11版本@ContributesAndroidInjector簡化流程

如果爲了使用,直接使用ContributesAndroidInjector註解方式即可。

 

1. 2.10版本複雜的方式

此種方式主要是爲了大致瞭解實現的邏輯,不具備實際開發用處。

 

1.0 導包

在Dagger的基礎上新增Android定製支持。

    // dagger2
    implementation 'com.google.dagger:dagger:2.19'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.19'
    // dagger android
    implementation 'com.google.dagger:dagger-android:2.19'
    implementation 'com.google.dagger:dagger-android-support:2.19'
    annotationProcessor 'com.google.dagger:dagger-android-processor:2.19'

1.1 依賴創建

和之前一樣,沒啥說的。

package com.fengzhen.anddagger.old;

public class User {
    private String name;
    private String password;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

提供一個用戶名爲“小明”的Module

package com.fengzhen.anddagger.old;

import dagger.Module;
import dagger.Provides;

@Module
public class UserModule {

    @Provides
    User provideLoginXM() {
        User login = new User();
        login.setName("小明");
        login.setPassword("123123");
        return login;
    }
}

 

1.2 依賴注入

這裏就和之前不一樣了,不再需要苦哈哈的去寫inject(),只需要在BaseActivity繼承Dagger-android提供的DaggerAppCompatActivity就可以了。

實際注入位置:

public class SecondActivity extends BaseActivity {

    @Inject
    User mLoginUser;

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

//        DaggerUserComponent.create().inject(this);

        Log.i("fengzhen1", "onCreate: " + mLoginUser.getName());
    }
}

BaseActivity也啥都沒寫:

package com.fengzhen.anddagger;

import android.os.Bundle;
import android.support.annotation.Nullable;

import dagger.android.support.DaggerAppCompatActivity;

/**
 * 創建時間:2018/12/12
 * 版   本:v1.0.0
 * 作   者:fengzhen
 * <p>
 * 功能描述:什麼都不用寫,只需要繼承 DaggerAppCompatActivity 就好了
 */
public class BaseActivity extends DaggerAppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
}

 

1.3 讓這一切被Dagger所知曉

這也是做出改動的一個環節。還是1 2 3一步一步先實現功能。

 

1. 創建AppComponent。管理所有的子模塊的Module。這裏的BuildersModule相當於一個子模塊;AndroidSupportInjectionModule 是Dagger-android提供的如四大組件、Fragment等的底層注入,後面簡單看看。

package com.fengzhen.anddagger;

import javax.inject.Singleton;

import dagger.Component;
import dagger.android.AndroidInjector;
import dagger.android.support.AndroidSupportInjectionModule;

@Singleton
@Component(modules = {
        BuildersModule.class,
        AndroidSupportInjectionModule.class})
public interface AppComponent extends AndroidInjector<MyApplication> {

    @Component.Builder
    abstract class Builder extends AndroidInjector.Builder<MyApplication> {
    }
}

 

2. 子模塊BuildersModule,綁定具體的UserComponent。(之前/之後 是2.11對比2.10 不用看)

package com.fengzhen.anddagger;

import android.app.Activity;

import com.fengzhen.anddagger.old.SecondActivity;
import com.fengzhen.anddagger.old.UserComponent;
import com.fengzhen.anddagger.old.UserModule;

import dagger.Binds;
import dagger.Module;
import dagger.android.ActivityKey;
import dagger.android.AndroidInjector;
import dagger.android.ContributesAndroidInjector;
import dagger.multibindings.IntoMap;

// ContributesAndroidInjector之前
@Module(subcomponents = UserComponent.class)
public abstract class BuildersModule {

    @Binds
    @IntoMap
    @ActivityKey(SecondActivity.class)
    abstract AndroidInjector.Factory<? extends Activity> bindSecondActivityInjectorFactory(
            UserComponent.Builder builder
    );
}

// ContributesAndroidInjector之後
//@Module
//public abstract class BuildersModule {
//    @ContributesAndroidInjector(modules = UserModule.class)
//    abstract SecondActivity secondActivityInjector();
//}

 

3. UserComponent主要是繼承AndroidInjector,並傳入Container泛型具體容器。(befor/after 是Dagger2基礎和Dagger-android對比,不用看)

package com.fengzhen.anddagger.old;

import dagger.Subcomponent;
import dagger.android.AndroidInjector;

//// befor
//@Component(modules = UserModule.class)
//public interface UserComponent {
//    void inject(SecondActivity secondActivity);
//}

/**
 * 主要申明注入到的具體位置
 */
// after
@Subcomponent(modules = UserModule.class)
public interface UserComponent extends AndroidInjector<SecondActivity> {

    @Subcomponent.Builder
    abstract class Builder extends AndroidInjector.Builder<SecondActivity> {
    }
}

 

4.創建MyApplication並且繼承DaggerApplication,將整個邏輯鏈接起來,別忘了manifests進行註冊。

package com.fengzhen.anddagger;

import dagger.android.AndroidInjector;
import dagger.android.DaggerApplication;

public class MyApplication extends DaggerApplication {
    @Override
    protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
        return DaggerAppComponent.builder().create(this);
    }
}

如此,整個注入就完成。不再需要每個Container去inject,簡直不要太爽。

 

1.4 源碼看了一下 結合 生成的代碼

1. DaggerAppCompatActivity主要就調用了一句代碼 AndroidInjection.inject(this),然後與AppComponet關聯,繼而關聯整個注入鏈。

2. MembersInjector<T> 通過泛型injectMembers()方法獲得具體的——UserComponent傳入的泛型SecondActivity——Container類型。實現在BaseActivity中進行具體的容器注入。

3. DaggerApplication實現HasActivityInjector接口,activityInjector()方法獲取到全局的Application級別的AndroidInjector注入器。之後DaggerAppCompatActivity中inject(this)傳入具體的容器注入。

4.AndroidSupportInjectionModule以及AndroidInjectionModule實現了具體的容器級別的注入,當然應用層級無法感知。

 

2. 2.11版本@ContributesAndroidInjector

BuildersModule改一下就可以了,而且UserComponent可以不寫,可以不寫。其他不變~~

package com.fengzhen.anddagger;

import com.fengzhen.anddagger.old.SecondActivity;
import com.fengzhen.anddagger.old.UserModule;

import dagger.Module;
import dagger.android.ContributesAndroidInjector;

// ContributesAndroidInjector之前
//@Module(subcomponents = UserComponent.class)
//public abstract class BuildersModule {
//
//    @Binds
//    @IntoMap
//    @ActivityKey(SecondActivity.class)
//    abstract AndroidInjector.Factory<? extends Activity> bindSecondActivityInjectorFactory(
//            UserComponent.Builder builder
//    );
//}

// ContributesAndroidInjector之後
@Module
public abstract class BuildersModule {
    @ContributesAndroidInjector(modules = UserModule.class)
    abstract SecondActivity secondActivityInjector();
}

紙上得來終覺淺,以後實際項目中用到了的時候在研究補充吧,比如侵入性太高的問題也還不知道對實際項目有什麼影響。

 

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