Gloading是一個github開源項目,可以用來深度解耦Android App中全局載入中、載入失敗及空數據視圖,也用這個項目中的思路可以進行類似的View解耦情形。
基本介紹
- 外文名:Gloading
- 開發語言:android(java)
- 開源時間:2019-03-17
- 作用:解耦
主要特點,背景介紹,解耦方式,使用Gloading來解耦,
主要特點
- 深度解耦Android App中全局載入中、載入失敗及空數據視圖,為組件化改造過程中的解耦長征助力
- 分離全局載入狀態視圖的實現和使用
- 不需要在每個頁面的布局檔案中額外添加載入狀態視圖
- 可用於Activity、Fragment,也可用於為某個View顯示載入狀態,還可用於各種列表Item(ListView、RecyclerView等)
- 輕量級:只有一個java檔案,沒有任何其它依賴,不到300行,其中注釋占100+行,aar僅6K
- 兼容性好:
- android系統版本從api 1開始兼容
- 兼容絕大多數第三方炫酷的LoadingView(在Adapter中將其作為View提供給Gloading)
背景介紹
Loading動畫幾乎每個Android App中都有。
一般在需要用戶等待的場景,顯示一個Loading動畫可以讓用戶知道App正在載入數據,而不是程式卡死,從而給用戶較好的使用體驗。
同樣的道理,當載入的數據為空時顯示一個數據為空的視圖、在數據載入失敗時顯示載入失敗對應的UI並支持點擊重試會比白屏的用戶體驗更好一些。
載入中、載入失敗、空數據的UI風格,一般來說在App內的所有頁面中需要保持一致,也就是需要做到全局統一。
傳統的做法
- 定義一個(或多個)顯示不同載入狀態的控制項或者xml布局檔案(例如:LoadingView)
- 每個頁面的布局中都寫上這個view
- 在BaseActivity/BaseFragment中封裝LoadingView的初始化邏輯,並封裝載入狀態切換時的UI顯示邏輯,暴露給子類以下方法:
- void showLoading;//調用此方法顯示載入中的動畫
- void showLoadFailed;//調用此方法顯示載入失敗界面
- void showEmpty;//調用此方法顯示空頁面
- void onClickRetry;//子類中實現,點擊重試的回調方法
- 在BaseActivity/BaseFragment的子類中可通過上一步的封裝比較方便地使用載入狀態顯示功能
這種使用方式耦合度太高,每個頁面的布局檔案中都需要添加LoadingView,使用起來不方便而且維護成本較高,一旦UI設計師需要更改布局,修改起來成本較高。
好一點的封裝方法
- 定義一個(或多個)顯示不同載入狀態的控制項或者xml布局檔案(例如:LoadingView)
- 定義一個工具類(LoadingUtil)來管理LoadingView,不同狀態顯示不同的UI(或者在多個View之間切換顯示)
- 在BaseActivity/BaseFragment中對LoadingUtil的使用進行封裝,暴露給子類以下方法:
- void showLoading;//調用此方法顯示載入中的動畫
- void showLoadFailed;//調用此方法顯示載入失敗界面
- void showEmpty;//調用此方法顯示空頁面
- void onClickRetry;//子類中實現,點擊重試的回調方法
- abstract int getContainerId;//子類中實現,LoadingUtil動態創建LoadingView並添加到該方法返回id對應的控制項中
- 在BaseActivity/BaseFragment的子類中可通過上一步的封裝比較方便地使用載入狀態顯示功能
這種封裝的好處是通過封裝動態地創建LoadingView並添加到指定的父容器中,讓具體頁面無需關注LoadingView的實現,只需要指定在哪個容器中顯示即可,很大程度地進行了解耦。如果公司只在一個App中使用,這基本上就夠了。
但是,這種封裝方式還是存在耦合:頁面與它所使用的LoadingView仍然存在綁定關係。如果需要復用到其它App中,因為每個App的UI風格可能不同,對應的LoadingView布局也可能會不一樣,要想復用必須先將頁面與LoadingView解耦。
解耦方式
梳理一下我們需要實現的效果
- 頁面的LoadingView可切換,且不需要改動頁面代碼
- 頁面中可指定LoadingView的顯示區域(例如導航欄Title不希望被LoadingView覆蓋)
- 支持在Fragment中使用
- 支持載入失敗頁面中點擊重試
- 兼容不同頁面顯示的UI有細微差別(例如提示文字可能不同)
2. 確定思路
說到View的解耦,很容易聯想到Android系統中的AdapterView(我們常用的GridView和ListView都是它的子類)及support包里提供的ViewPager、RecyclerView等,它們都是通過Adapter來解耦的,將自身的邏輯與需要動態變化的子View進行分離。我們也可以按照這個思路來解耦LoadingView。
使用Gloading來解耦
Gloading是一個基於Adapter思路實現的深度解耦App中全局LoadingView的輕量級工具(只有一個java檔案,不到300行,其中注釋占100+行,aar僅6K)
1、 依賴Gloading
compile 'com.billy.android:gloading:1.0.0'
2、 創建Adapter,在getView方法中實現創建各種狀態視圖(載入中、載入失敗、空數據等)的邏輯
Gloading不侵入UI布局,完全由用戶自定義
3、 初始化Gloading的默認Adapter
Gloading.initDefault(new GlobalAdapter());
註:可以用AutoRegister在Gloading類裝載進虛擬機時自動完成初始化註冊,無需在app層執行註冊,耦合度更低
4、在需要使用LoadingView的地方獲取Holder
//在Activity中顯示, 父容器為: android.R.id.content
Gloading.Holder holder = Gloading.getDefault().wrap(activity);
//需要支持載入失敗後點擊重試
Gloading.Holder holder = Gloading.getDefault().wrap(activity).withRetry(retryTask);
or
//為某個View顯示載入狀態
//Gloading會自動創建一個FrameLayout,將view包裹起來,LoadingView也顯示在其中
Gloading.Holder holder = Gloading.getDefault().wrap(view);
//需要支持載入失敗後點擊重試
Gloading.Holder holder = Gloading.getDefault().wrap(view).withRetry(retryTask);
5、 使用Holder來顯示各種載入狀態
//顯示載入中的狀態,通常是顯示一個載入動畫
holder.showLoading()
//顯示載入成功狀態(一般是隱藏LoadingView)
holder.showLoadSuccess()
//顯示載入失敗狀態
holder.showFailed()
//數據載入完成,但數據為空
holder.showEmpty()
//如果以上默認提供的狀態不能滿足使用,可使用此方法調用其它狀態
holder.showLoadingStatus(status)
6、 兼容多App場景下的頁面、View的復用
每個App的LoadingView可能會不同,只需為每個App提供不同的Adapter,不同App調用不同的Gloading.initDefault(new GlobalAdapter);,具體頁面中的使用代碼無需改動。
註:如果使用AutoRegister,則只需在不同App中創建各自的Adapter實現類,無需手動調用Gloading.initDefault註冊。只需改動2處gradle檔案即可:
- 修改根目錄build.gradle,添加對AutoRegister的依賴
buildscript {
//...
dependencies {
//...
classpath 'com.billy.android:autoregister:使用最新版'
}
}
- 修改主application module下的build.gradle,添加如下代碼即可實現Adapter的自動註冊
apply plugin: 'auto-register'
autoregister {
registerInfo = [
[
'scanInterface' : 'com.billy.android.loading.Gloading$Adapter'
, 'codeInsertToClassName' : 'com.billy.android.loading.Gloading'
, 'registerMethodName' : 'initDefault'
]
]
}