元件化架構Dagger2無縫連線開發

cuieney發表於2017-11-08

前言

可以說已經一個多月沒有更新了,mdzz這個月一直在趕專案節奏,可算是度過了這個階段。也不能說這個月沒有收穫,新專案中又總結了不少經驗,這次就來分享一下所感所得吧,記得之前寫過一篇文章說的是元件化開發詳解這篇文章可能與他息息相關。只不過是把Dagger引入了元件化開發專案中,之前那篇文章的重點是如何搭建一個元件化架構,方便團隊開發配合。這篇文章的重點是把dagger引入元件化開發架構中,之前搭建元件化開發也沒想到用Dagger引入專案,因為坑不是一般的多,各種錯誤,各種bug,讓你頭疼。這篇文章會把這些問題一一闡述,達到無縫連線

坑列表

大部分都是放置位置的問題。這樣會讓你減少很多module裡面的程式碼

  1. 元件化架構Dagger如何配置
  2. Module放置位置
  3. XXXComponent位置如何放置,不會出現找不到Module
  4. Base App/Activity/Fragment 如何封裝

各個Module的Gradle Dagger配置

先把簡單的架構圖放上面 方便下面一一敘述

從上圖可以看出每個module都會依賴於最下層的Library

1.那麼我們先說在Library的gradle中如何配置吧

dependencies {
  compile 'com.google.dagger:dagger:2.x'
  annotationProcessor 'com.google.dagger:dagger-compiler:2.x'
}複製程式碼

2.那麼接下來我們來看看Module中如何配置Gradle檔案呢!

dependencies {
  annotationProcessor 'com.google.dagger:dagger-compiler:2.x'
}複製程式碼

看到上面程式碼是不是很驚訝,為什麼在上層module中為什麼還要重複依賴呢,出現了同樣的配置。

 annotationProcessor 'com.google.dagger:dagger-compiler:2.x'複製程式碼

大家應該都明白這行程式碼的主要功能是用於生成程式碼的。底層library裡面不是已經有了嗎?為什麼在上層module中還出現呢?這是一個坑。下面我會一一解釋

Dagger Module放置位置

其實dagger 中的Module的放置位置很重要,因為module 是用於component注入到各個Activity裡面的,之前的mv*這些架構Di這些東西都是放在Application module裡面的,但是我們既然是元件化開發,肯定要知道我們的初衷,我們的BaseLibrary到底是幹嘛的。給上層module提供各種工具各種方便,讓各個module開發互相不干擾。

那麼當然是把各種module放在最底層的library中的瞭如ActivityModule, FragmentModule,AppModule 這些我只是簡單的舉例,可能還有很多Module,其實這裡說到module 可能也會明白上面的為什麼在最底層library中也新增程式碼生成

 annotationProcessor 'com.google.dagger:dagger-compiler:2.x'複製程式碼

為了生成相應的module程式碼。提供上面component使用。

XXXComponent位置如何放置,不會出現找不到Module

這個問題也是我在開發中出現的,由於之前只是在mv*架構中使用Dagger 在元件化架構中開發知道坑多,沒用Dagger,那麼我們來看看如何放置我們的Activity/Fragment/App Component等等這些位置。這裡我只舉例而我們的ActivityComponent和AppComponent的放置位置。

1.AppComponent如何放置,當然是放在我們的BaseLibrary中了,因為是App全域性都需要用的,所以我們這個可以寫在我們最底層的Library中,然後上層module都可以用到。其實之前我是每個Module都放的,發現這樣寫真是很多冗餘的程式碼,沒有脫離mvp那
個結構 導致的。

2.ActivityComponent如何放置呢?可能會比較麻煩因為每個上層Module用到的都要放置一個對應的ActivityComponent

@PerActivity
@Component(dependencies = BaseAppComponent.class, modules = ActivityModule.class)
public interface ActivityComponent {
    Activity getActivity();
    void inject(VoiceActivity mainActivity);
ity);
}複製程式碼

從上面程式碼也可以看出 我們為什麼每個元件Module為什麼都放置一個ActivityComponent,因為如果你放置在底層Library中,你根本不知道你的哪個activity要用到,而且library也是拿不到上層Module裡面的任何東西 底層library只是一個供給者 而非索取者。

但是我們的AppComponent不需要知道我們需要哪些東西,我們只是負責提供東西。

Base App/Activity/Fragment 如何封裝

如果你的專案按照上面的配置,這時你已經繞過了很多坑的地方

說道封裝Base 這時候需要提到一個問題就是之前那一篇文章說道了一個問題 module與Application之間呼叫的問題 我也提供瞭解決方案,就是在底層Library中寫個BaseApplication來供上層呼叫。

那麼我們迴歸正題,這裡只說App 和 Activity的Base封裝

  1. 底層Library中的BaseApp如何封裝呢?看程式碼
public abstract class BaseApp extends Application {
    protected static BaseApp app;
    public static BaseApp getInstance() {
        return app;
    }

    protected abstract void initSDK();

    public BaseAppComponent getAppComponent() {
        return  DaggerBaseAppComponent.builder()
                .appModule(new AppModule(this))
                .retrofitModule(new RetrofitModule(this))
                .build();
    }

}複製程式碼

這時候就體現了上面說道的Component和Module放置位置的重要性。 我們的module 和APPComponent都是放在底層Library

  1. BaseActivity的封裝。這個我感覺比較靈活,自己根據自己的專案來進行封裝,怎麼樣都行。給大家看一下我的程式碼,我是這樣的
public abstract class BaseMvpActivity<T extends BasePresenter> extends AppCompatActivity implements BaseView {
    @Inject
    protected T mPresenter;
    public static Activity mContext;
    private Unbinder mUnBinder;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(initLayout());
        mContext = this;
        mUnBinder = ButterKnife.bind(this);
        initInject();
        if (mPresenter != null) {
            mPresenter.attachView(this);
        }
        initData();
    }


    protected abstract void initInject();


    protected ActivityComponent getActivityComponent() {
        return DaggerActivityComponent
                .builder()
                .baseAppComponent(BaseApp.getInstance().getAppComponent())
                .activityModule(getActivityModule())
                .build();
    }

    protected ActivityModule getActivityModule() {
        return new ActivityModule(this);
    }

    /**
     * 初始化佈局
     */
    public abstract int initLayout();


    /**
     * 初始化資料
     */
    public abstract void initData();


    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mPresenter != null)
            mPresenter.detachView();
        mUnBinder.unbind();
    }


}複製程式碼

沒什麼亮點啥的,就是簡單的封裝,我這專案是基於元件化+MVP開發的,可能你看到了Presenter這些東西。

總結

其實主要的東西還是講解如何在元件化開發中配置Dagger 讓你更省時更省力,節省程式碼量和錯誤量。繞過很多坑

ending

上面可能有說不明白的,可以直接評論中@我,我會及時迴應,或者有說哪裡不正確的有優化的地方都可以@我,歡迎討論,如果這篇文章反應比較好的話,打算出一篇元件化架構+MVP架構混合開發。希望文章帶來的是收穫而非時間的浪費,謝謝大家的支援

相關文章