天天看點

android 元件化dagger2,Android子產品化之ButterKnife和Dagger2的使用

通常來說,我們引入一個第三方庫,隻需要在OpenSourceLibrary中的gradle檔案中添加一個依賴即可,這樣任何一個業務module都可以使用該庫的功能。但是,有一種庫例外,這種庫會利用用apt或annotationProcessor生成代碼。這種庫使用大量使用注解,然後在編譯期間生成代碼,能夠為開發者省很多功夫,比如大名鼎鼎的ButterKnife和Dagger2,涉及到這種庫時,在用到的每一個module中都要有相應的配置。這裡我們介紹下在子產品化工程中如何使用(自己琢磨的,有更好的方式歡迎告知)。

ButterKnife的使用

引入依賴

由于butterknife之前是不支援library中使用的,後來更新後利用插件生成了R2檔案,支援library使用。對于我們的module來說,既可以是一個Application,也可以是一個library,在Application時用的R檔案,在library又必須使用R2檔案,這樣就比較坑爹。為了統一,我們在所有的module以及App子產品中都使用R2檔案。

首先這樣做:在OpenSourceLibrary的gradle檔案中添加(這個依賴是每個module都要用的,統一放在OpenSourceLibrary中)

compile 'com.jakewharton:butterknife:8.6.0'

然後這樣做:(注意:以下步驟需要在所有使用Butterknife的子產品中進行)

引入butterknife為library準備的插件,該module的gradle中添加:

apply plugin: 'com.jakewharton.butterknife‘

同時添加編譯時的依賴:

buildscript {

repositories {

mavenCentral()

}

dependencies {

com.jakewharton:butterknife-gradle-plugin:8.6.0

com.android.tools.build:gradle:2.3.1

}

}

最後在dependencies中添加:

dependencies {

annotationProcessor 'com.jakewharton:butterknife-compiler:8.6.0'

}

butterknife注入的封裝

通常來說,我們使用butterknife都會在基類中注入好,然後子類中就不用注入,而是直接使用。在這裡,有一個問題,我們的BaseActivity是放在第二層的基礎業務層的,示例代碼中放在CommonBusiness子產品中,而它的子類是放在我們的業務包中的,這樣沒有問題嗎?實踐證明,沒有問題:

public abstract class BaseActivity extends AppCompatActivity {

private Unbinder unbinder;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

}

@Override

public void setContentView(@LayoutRes int layoutResID) {

super.setContentView(layoutResID);

unbinder = ButterKnife.bind(this);

}

@Override

protected void onDestroy() {

super.onDestroy();

unbinder.unbind();

}

}

通過以上兩個步驟,butterknife就可以正常使用了。

Dagger2的使用

Dagger2的依賴引入

和butterknife一樣,首先要在OpensourceLibrary中添加一個所有子產品都會用到的依賴:

compile 'com.google.dagger:dagger:2.x'

然後,在每一個要使用Dagger2的子產品的gradle檔案中添加如下語句:

dependencies {

annotationProcessor 'com.google.dagger:dagger-compiler:2.x'

}

這樣在每個子產品中就可以使用了

使用dagger2

使用dagger2分為兩種情況,一種是通過dagger2注入本子產品的對象,以CommonBusiness子產品中的HouseDetail為例,

首先編寫Module檔案

@Module

public class CommonBusinessModule {

@Provides

public HouseDetail provideHouseDetail(){

return new HouseDetail();

}

}

然後編寫Component檔案

@Component(modules = CommonBusinessModule.class)

public interface CommonBusinessComponent {

void inject(LoginActivity loginActivity);

}

最後在LoginActivity中注入使用

@Inject

HouseDetail houseDetail;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_login);

targetUrl = getCurModuleUrl();

if(targetUrl == null){

targetUrl = ConstantRouter.APP_MAINACTIVITY;

}

DaggerCommonBusinessComponent.builder().build().inject(this);

Log.d("longyi",houseDetail.toString());

//此處用來模拟登入事件

progressBar.postDelayed(new Runnable() {

@Override

public void run() {

DataCenter.getInstance().setLogin(true);

ARouter.getInstance().build(targetUrl).navigation();

LoginActivity.this.finish();

}

},2000);

}

另外一種情況就是在業務層的module中通過dagger2注入基礎業務層中的對象,比如在InstantMessagingModule中注入CommonBusiness中的HouseDetail對象。

首先直接編寫Component檔案

@Component(modules = { CommonBusinessModule.class})

public interface ImComponenment {

void inject(InstantMessagingMainActivity activity);

}

這裡的module依賴直接指定為CommonBusiness中的module檔案就可以了。

另外還有一種方式,看代碼

@Module

public class ImModule extends CommonBusinessModule{

@Provides

public SecondHouse provideSecond(){

return new SecondHouse();

}

}

@Component(modules = {ImModule.class })

public interface ImComponenment {

void inject(InstantMessagingMainActivity activity);

}

這裡是編寫了自己的自己子產品的module檔案,然後繼承了CommonBusinessModule,這樣在Component中直接指定ImModule.class為依賴既可以了。

總結

涉及到有編譯期間動态生成代碼的,最起碼,每個子產品中都要有annotationProcessor配置(或apt)。