app中請(qǐng)求服務(wù)器數(shù)據(jù)后進(jìn)行繪制頁(yè)面時(shí)會(huì)有多種狀態(tài),比如網(wǎng)絡(luò)請(qǐng)求過(guò)程中l(wèi)oading狀態(tài),加載出錯(cuò)狀態(tài),獲取數(shù)據(jù)發(fā)現(xiàn)數(shù)據(jù)為空狀態(tài),加載過(guò)程中網(wǎng)絡(luò)異常頁(yè)面和正常加載完畢的數(shù)據(jù)展示頁(yè)面。
一般的做法是將多個(gè)狀態(tài)封裝成自定義View,然后在每一個(gè)頁(yè)面的布局文件中引入,在加載數(shù)據(jù)時(shí)展示不同的狀態(tài)。
可以有另一種方案,通過(guò)代碼編寫(xiě)View的方式,將自定義View添加到頁(yè)面中,這樣可以避免了在每一個(gè)布局中手動(dòng)添加布局文件的麻煩,并且如果有抽出BaseActivity和BaseFragment的話,使用起來(lái)就更簡(jiǎn)單了(當(dāng)然,原先在布局文件中加入自定義View的方法也是可以在Base中抽取出成員變量的)
但是如何抽取呢?因?yàn)獒槍?duì)不同的頁(yè)面展示不同狀態(tài)的父布局是不確定的,可以采用比較簡(jiǎn)單的方式,給每一個(gè)布局的根布局添加id,然后獲取到根布局,使用addView方法將自定義View添加到布局中。不過(guò)這樣相對(duì)來(lái)說(shuō)太麻煩了一點(diǎn)。
根據(jù)頁(yè)面劃分的話,有三種情況,Activity,F(xiàn)ragment或者View
所以我們可以根據(jù)這三種情況來(lái)判斷,然后獲取到不同的根布局,然后添加不同狀態(tài)的View
if (mTarget == null) {
throw new NullPointerException("參數(shù)不能為空");
}
Context context = null;
if (mTarget instanceof Activity) {
// 認(rèn)為 contentLayout 是 activity 的跟布局
// 所以它的父控件就是 android.R.id.content
context = (Activity) mTarget;
mParentLayout = ((Activity) context).findViewById(android.R.id.content);
mContentLayout = mParentLayout != null ? mParentLayout.getChildAt(0) : null;
} else if (mTarget instanceof View) {
// 有直接的父控件
mContentLayout = (View) mTarget;
context = ((View) mTarget).getContext();
mParentLayout = (ViewGroup) mContentLayout.getParent();
} else if (mTarget instanceof Fragment) {
// 有直接的父控件
mContentLayout = ((Fragment) mTarget).getView();
context = ((Fragment) mTarget).getActivity();
mParentLayout = (ViewGroup) mContentLayout.getParent();
} else if (mTarget instanceof android.support.v4.app.Fragment) {
// 有直接的父控件
mContentLayout = ((android.support.v4.app.Fragment) mTarget).getView();
context = ((android.support.v4.app.Fragment) mTarget).getActivity();
mParentLayout = (ViewGroup) mContentLayout.getParent();
} else {
throw new IllegalArgumentException("參數(shù)必須為view、Fragment或者Activity類型");
}
還有一個(gè)問(wèn)題就是默認(rèn)狀態(tài)布局和自定義布局的設(shè)置,因?yàn)橐粋€(gè)app包含的很多頁(yè)面不可能所有頁(yè)面都有相同的狀態(tài)頁(yè)面(A頁(yè)面的空布局頁(yè)面和B頁(yè)面的空布局不一定一樣)


所以根據(jù)這個(gè)情況設(shè)置了兩個(gè)方案,設(shè)置默認(rèn)布局,保存在SparseArray<View>中,然后設(shè)置MultiStatusLayoutManager為單例,在其他使用統(tǒng)一默認(rèn)狀態(tài)布局的頁(yè)面都使用這個(gè)單例變量來(lái)展示不同的狀態(tài)布局;并且提供創(chuàng)建普通對(duì)象的方法,以供設(shè)置自定義狀態(tài)布局。