一個很棒的 Android APP框架

最近在 github 上看到一個 android 的框架,結合了 Rxjava + retrofit + dagger2 + mvp,結合了當下比較流行的框架,并且項目層次非常清晰,易于擴展和維護

github 地址

項目總覽

可以看到項目采用的 MVP 架構( http://xuyushi.github.io/2016/02/28/MVP/)

與常規的 MVP 不同的是,在 modle 層和 view 層通過EventBus 連接,當數據發生變化時,發出對應的 event,注冊了這個 event 的 view會采取對應的措施。舉個例子,退出登錄用在這樣的情形就很合適,在退出登錄后,我們可能不止一個 view 會發生變化,如果把這些寫在每一個 Presenter 中無疑是很不簡潔的代碼

在 modle 層中,抽象出了一個 DataManger,通過DataManger 我們與數據的具體實現進行了解耦,在 P 層我們無需關注數據是來自 DB ,SP 還是網絡。我們只關心拿到的數據對象,而在DataManger 和 具體的數據實現中 還有一層 Helper 層,這層封裝了對數據的具體操作,比如 DBHelper、SPHelper、RetrofitServie,有了這一層封裝可以很方便我們進行擴展。

DataManger 和 Helper累 中的方法拿到的都是 Observeable ,從而方便我們對這個流進行操控。

具體分析

dagger2

項目使用了dagger2 依賴注入框架解耦個層,使得單測和框架替換變得很容易

ApplicationComponent

首先看 ApplicationComponent ,他有一個 Moudle ,并且將這個 Moudle 中的提供的構造方法暴露出來,可以看到DatabaseHelper、PreferencesHelper等暴露出來的都是全局使用的對象

@Singleton
@Component(modules = ApplicationModule.class)
public interface ApplicationComponent {

    void inject(SyncService syncService);

    @ApplicationContext Context context();
    Application application();
    RibotsService ribotsService();
    PreferencesHelper preferencesHelper();
    DatabaseHelper databaseHelper();
    DataManager dataManager();
    Bus eventBus();

}

###

@Module
public class ApplicationModule {
    protected final Application mApplication;

    public ApplicationModule(Application application) {
        mApplication = application;
    }

    @Provides
    Application provideApplication() {
        return mApplication;
    }

    @Provides
    @ApplicationContext
    Context provideContext() {
        return mApplication;
    }

    @Provides
    @Singleton
    Bus provideEventBus() {
        return new Bus();
    }

    @Provides
    @Singleton
    RibotsService provideRibotsService() {
        return RibotsService.Creator.newRibotsService();
    }

}

可以看到在 ApplicationModule 中的 provide 方法暴露出的方法對比 ApplicationComponent 中需要的方法,發現還缺了幾項。 DatabaseHelper 、 PreferencesHelper 、 DataManager

這是為毛捏? 熟悉 dagger2的小伙伴可能已經明白了

復習 dagger

dagger 創建類實例有2個維度可以創建

  • 步驟1:查找Module中是否存在創建該類的方法。
  • 步驟2:若存在創建類方法,查看該方法是否存在參數
    • 步驟2.1:若存在參數,則按從 步驟1 開始依次初始化每個參數
    • 步驟2.2:若不存在參數,則直接初始化該類實例,一次依賴注入到此結束
  • 步驟3:若不存在創建類方法,則查找 Inject注解的構造函數 ,看構造函數是否存在參數

    • 步驟3.1:若存在參數,則從 步驟1 開始依次初始化每個參數
    • 步驟3.2:若不存在參數,則直接初始化該類實例,一次依賴注入到此結束

      因為在使用第三方代碼時,我們無法修改源碼的構造方法,所以使用 Module 來提供注入構造

所以再回來看 DataManager 的構造方法

@Inject
   public DataManager(RibotsService ribotsService, PreferencesHelper preferencesHelper,
 DatabaseHelper databaseHelper, EventPosterHelper eventPosterHelper) {
       mRibotsService = ribotsService;
       mPreferencesHelper = preferencesHelper;
       mDatabaseHelper = databaseHelper;
       mEventPoster = eventPosterHelper;
   }

用 @Inject 標注了構造方法,當注入了 DataManager 時,在 module 中找不到對應的 provide 方法,變會在構造方法中尋找,在遞歸的找參數中的注入…

以下用一張圖來概括

data

來看下整體的 data 包

分為 local 和 remote、model幾個包

  • local 主要是 SP、DB 相關
  • remote 是網絡相關的操作,這里就是一個 retrofit 的 service
  • modle 中定義了 java bean

retrofit

再來看下 retrofit service 中

public interface RibotsService {

    String ENDPOINT = "https://api.ribot.io/";

    @GET("ribots")
    Observable<List<Ribot>> getRibots();

    /******** Helper class that sets up a new services *******/
    class Creator {

        public static RibotsService newRibotsService() {
            Gson gson = new GsonBuilder()
                    .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
                    .create();
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(RibotsService.ENDPOINT)
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .build();
            return retrofit.create(RibotsService.class);
        }
    }
}

在構建了 Retrofit 后再構建 service ,要是我來寫的話會把 Retrofit 也用 dagger 注入的方式來提供。

DataManger

DataManger 基本上放的就是業務邏輯了,具體看個例子

public Observable<Ribot> syncRibots() {
    return mRibotsService.getRibots()
            .concatMap(new Func1<List<Ribot>, Observable<Ribot>>() {
                @Override
                public Observable<Ribot> call(List<Ribot> ribots) {
                    return mDatabaseHelper.setRibots(ribots);
                }
            });
}

在 syncRibots 方法中,我們通過retrofit 獲得網絡的數據,再用 DB 存儲,再把結果用 Observable 的結構返回給 P層,在這個例子中是在一個 service 中調用這個方法

MVP

關于 MVP 這一塊,個人的建議是使用谷歌官方的例子。更為簡潔明了

也可以看我的這一篇實踐

同樣 P V 直接也可以使用 dagger 解耦。

 

來自: http://xuyushi.github.io/2016/06/18/Android APP 新框架/

 

 本文由用戶 sfoj6993 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!