现在的app基本上都是从服务器获取数据 ,并把数据显示到页面上。我之前用的是dialog,但是dialog只有在加载数据的时候显示,并没有对加载数据结果进行处理(比如说加载失败出现提示并点击再次进行请求等)这样的效率并不是很高,为此抽取出了一个LoadingPage配合LoadingBaseActivity和BaseFragment使用大大增加了开发效率。
这里定义了5种状态和对应状态显示的view,对外暴露了3个方法:
- 方法1、getLayoutId() 获取数据加载成功后显示的布局id,一般就是XxxActivitiy和XxxFragment的布局
- 方法2、initView() 子类关于View的操作(如ButterKnife的初始化,可以参考LoadingBaseActivity)都必须在这里面
- 方法3、loadData() 当网络获取失败 点击进行网络请求时调用,根据网络获取的数据返回状态,每一个子类的获取网络返回的都不一样,所以要交给子类去完成。
这里就以逗萌吧的例子展示下。说了那么多,直接贴代码看得更清晰。至于怎么使用可以参考LoadingBaseActivity和BaseFragment。
public abstract class LoadingPage extends FrameLayout {
public static final int STATE_UNKNOWN = 0;
public static final int STATE_LOADING = 1;
public static final int STATE_ERROR = 2;
public static final int STATE_EMPTY = 3;
public static final int STATE_SUCCESS = 4;
private View loadingView; // 加载中的界面
private View errorView; // 错误界面
private View emptyView; // 空界面
public View contentView; // 加载成功的界面
private AnimationDrawable mAnimationDrawable;//imageview的动画
private ImageView img;//加载时显示的imageview
public int state = STATE_UNKNOWN;
private Context mContext;
public LoadingPage(Context context) {
this(context,null);
}
public LoadingPage(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public LoadingPage(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
init();//初始化4种界面
}
private void init() {
this.setBackgroundColor(getResources().getColor(R.color.colorPageBg));
//把loadingView添加到frameLayout上
if (loadingView == null) {
loadingView = createLoadingView();
this.addView(loadingView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
//把emptyView添加到frameLayout上
if (emptyView == null) {
emptyView = createEmptyView();
this.addView(emptyView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
//把errorView添加到frameLayout上
if (errorView == null) {
errorView = createErrorView();
this.addView(errorView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
showPage();//根据状态显示界面
}
private View createLoadingView() {
loadingView = LayoutInflater.from(mContext).inflate(R.layout.loadingpage_state_loading, null);
img = (ImageView) loadingView.getRootView().findViewById(R.id.img_progress);
// 加载动画 这边也可以直接用progressbar
mAnimationDrawable = (AnimationDrawable) img.getDrawable();
// 默认进入页面就开启动画
if (!mAnimationDrawable.isRunning()) {
mAnimationDrawable.start();
}
return loadingView;
}
private View createEmptyView() {
emptyView = LayoutInflater.from(mContext).inflate(R.layout.loadingpage_state_empty, null);
return emptyView;
}
private View createErrorView() {
errorView = LayoutInflater.from(mContext).inflate(R.layout.loadingpage_state_error, null);
errorView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
state = STATE_LOADING;
showPage();
loadData();
}
});
return errorView;
}
private void startAnimation() {
if (!mAnimationDrawable.isRunning()) {
mAnimationDrawable.start();
}
}
private void stopAnimation() {
if (mAnimationDrawable != null && mAnimationDrawable.isRunning()) {
mAnimationDrawable.stop();
}
}
public void showPage() {
if (loadingView != null) {
if (state == STATE_UNKNOWN || state == STATE_LOADING) {
loadingView.setVisibility(View.VISIBLE);
// 开始动画
startAnimation();
} else {
// 关闭动画
stopAnimation();
loadingView.setVisibility(View.GONE);
}
}
if (state == STATE_EMPTY || state == STATE_ERROR || state == STATE_SUCCESS) {
// 关闭动画
stopAnimation();
}
if (emptyView != null) {
emptyView.setVisibility(state == STATE_EMPTY ? View.VISIBLE : View.GONE);
}
if (errorView != null) {
errorView.setVisibility(state == STATE_ERROR ? View.VISIBLE : View.GONE);
}
if (state == STATE_SUCCESS) {
if (contentView == null) {
contentView = LayoutInflater.from(mContext).inflate(getLayoutId(), null);
addView(contentView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
initView();
}
contentView.setVisibility(View.VISIBLE);
} else {
if (contentView != null) {
contentView.setVisibility(View.GONE);
}
}
}
/**
* 1、
* @Description 初始化布局,当网络请求成功时显示
*/
protected abstract int getLayoutId();
/**
* 2、
* @Description 子类关于View的操作(如setAdapter)都必须在这里面,会因为页面状态不为成功,而binding还没创建就引用而导致空指针。
*/
protected abstract void initView();
/**
* 3、
* @Description 当网络获取失败 点击进行网络请求时调用
* 根据网络获取的数据返回状态,每一个子类的获取网络返回的都不一样,所以要交给子类去完成
*/
protected abstract void loadData();
}
网友评论