app中请求服务器数据后进行绘制页面时会有多种状态,比如网络请求过程中loading状态,加载出错状态,获取数据发现数据为空状态,加载过程中网络异常页面和正常加载完毕的数据展示页面。
一般的做法是将多个状态封装成自定义View,然后在每一个页面的布局文件中引入,在加载数据时展示不同的状态。
可以有另一种方案,通过代码编写View的方式,将自定义View添加到页面中,这样可以避免了在每一个布局中手动添加布局文件的麻烦,并且如果有抽出BaseActivity和BaseFragment的话,使用起来就更简单了(当然,原先在布局文件中加入自定义View的方法也是可以在Base中抽取出成员变量的)
但是如何抽取呢?因为针对不同的页面展示不同状态的父布局是不确定的,可以采用比较简单的方式,给每一个布局的根布局添加id,然后获取到根布局,使用addView方法将自定义View添加到布局中。不过这样相对来说太麻烦了一点。
根据页面划分的话,有三种情况,Activity,Fragment或者View
所以我们可以根据这三种情况来判断,然后获取到不同的根布局,然后添加不同状态的View
if (mTarget == null) {
throw new NullPointerException("参数不能为空");
}
Context context = null;
if (mTarget instanceof Activity) {
// 认为 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("参数必须为view、Fragment或者Activity类型");
}
还有一个问题就是默认状态布局和自定义布局的设置,因为一个app包含的很多页面不可能所有页面都有相同的状态页面(A页面的空布局页面和B页面的空布局不一定一样)
20180920233355681.png
20180920233404854.png
所以根据这个情况设置了两个方案,设置默认布局,保存在SparseArray<View>中,然后设置MultiStatusLayoutManager为单例,在其他使用统一默认状态布局的页面都使用这个单例变量来展示不同的状态布局;并且提供创建普通对象的方法,以供设置自定义状态布局。
网友评论