通常來說,我們引入一個第三方庫,隻需要在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)。