在app开发过程中很多时候我们需要访问网络,访问数据库等,此时app将会有多种状态,比如加载中,加载成功,加载失败,没有网络等等,此时如果我们使用弹出的方式告知用户,非常不友好。之前被产品爸爸说有种笨重的感觉,但是笨重这么抽象你告诉我我TM该怎么理解呢? 经过leader的暗示解答,终于知道原来他想要那种感觉,就是那种看起来不笨重的感觉,翻译过来就是使用多状态,那么应该怎么做呢?看到过有人封装在BaseFragment和BaseActivity,但是这样子做耦合度太高,而且看起来代码也比较笨重,是的又回到了笨重这个话题。 ####效果演示 那么笨重feel是怎样的呢?
那么一般我们应该怎么做呢? 看看下面的小图图: ####整体结构 那么它的整体结构是怎样的呢? 从上面的整体结构i图可以知道主要有以下方法:createView() 构造方法,这里重载了两个,分别使用默认的view以及使用you like view
onLoad() 加载方法,显示loadingview
onEmpty() 空数据,显示emptyView
onError() 加载出错,显示errorView
onNoNet() 没有网络,显示noNetView
onSuccess 加载成功,显示构造方法传入的contentView
onDestory() 资源回收
setOnRetryClick() 提供点击重新加载的接口
####使用 使用方法很简单,根据上面的整体结构
- 构造
StatusViewManager manager = StatusViewManager.createView(Context, ContentView);
- 加载
manager.onLoad()
- 根据情况调用各种状态
####代码实现 #####StatusViewManager
/*** Created by AmatorLee on 2017/7/12.*/public class StatusViewManager extends StatusInterface implements View.OnClickListener {private LayoutInflater mInflater;/*** 加载view*/private View mLoadView;/*** 错误view*/private View mErrorView;/*** 无数据view*/private View mEmptyView;/*** 实际view*/private View mContentView;/*** 无网络链接时得view*/private View mNoNetView;private RelativeLayout.LayoutParams mParams;/*** 保存状态view的container*/private RelativeLayout mStatusContainer;private Context mContext;/*** 避免重复添加*/private boolean isAddLoad, isAddEmpty, isAddNoNet, isAddError;/*** 可见状态*/public static final int V = View.VISIBLE;/**** 不可见状态*/public static final int G = View.GONE;/*** 重新加载接口*/private onRetryClick mOnRetryClick;/*** 切换到主线程改变view的状态*/private Handler mMainThreadHandler;private int empty_layout_id = -1;private int error_layout_id = -1;private int no_net_layout_id = -1;private int loading_layout_id = -1;public static final String ERROR = "error";public static final String EMPTY = "empty";public static final String NONET = "nonet";public static final String LOAD = "load";public void setOnRetryClick(onRetryClick onRetryClick) {mOnRetryClick = onRetryClick;}private StatusViewManager(Context context, View contentView, int loading_layout_id, int empty_layout_id, int error_layout_id, int no_net_layout_id) {super();this.loading_layout_id = loading_layout_id;this.empty_layout_id = empty_layout_id;this.error_layout_id = error_layout_id;this.no_net_layout_id = no_net_layout_id;mContentView = contentView;mMainThreadHandler = new Handler(Looper.getMainLooper());mContext = context;mInflater = LayoutInflater.from(context);mParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);mParams.addRule(RelativeLayout.CENTER_IN_PARENT);initView();setOnClick();initContainer();}private void setOnClick() {if (mEmptyView != null)mEmptyView.setOnClickListener(this);if (mNoNetView != null)mNoNetView.setOnClickListener(this);if (mErrorView != null)mErrorView.setOnClickListener(this);}public static StatusViewManager createView(Context context, View ContentView) {return new StatusViewManager(context, ContentView, -1, -1, -1, -1);}public static StatusViewManager createView(Context context, View contentView, int loading_layout_id, int empty_layout_id, int error_layout_id, int no_net_layout_id) {return new StatusViewManager(context, contentView, loading_layout_id, empty_layout_id, error_layout_id, no_net_layout_id);}@Overrideprotected void initView() {if (loading_layout_id == -1) {loading_layout_id = R.layout.layout_loading;}if (empty_layout_id == -1) {empty_layout_id = R.layout.layout_empty;}if (error_layout_id == -1) {error_layout_id = R.layout.layout_error;}if (no_net_layout_id == -1) {no_net_layout_id = R.layout.layout_no_net;}try {mLoadView = mInflater.inflate(loading_layout_id, null);mLoadView.setTag(LOAD);mErrorView = mInflater.inflate(error_layout_id, null);mErrorView.setTag(ERROR);mEmptyView = mInflater.inflate(empty_layout_id, null);mEmptyView.setTag(EMPTY);mNoNetView = mInflater.inflate(no_net_layout_id, null);mNoNetView.setTag(NONET);} finally {mInflater = null;}}@Overridepublic void initContainer() {mStatusContainer = new RelativeLayout(mContext);mStatusContainer.setLayoutParams(mParams);ViewGroup parent = (ViewGroup) mContentView.getParent();parent.addView(mStatusContainer);}@Overridepublic void onLoad() {mMainThreadHandler.post(new Runnable() {@Overridepublic void run() {if (mLoadView != null && !isAddLoad) {isAddLoad = true;mStatusContainer.addView(mLoadView, mParams);}show(STATUS.LOADING);}});}private void show(STATUS result) {switch (result) {case SUCCESS:changeVisiable(V, G, G, G, G);break;case LOADING:changeVisiable(G, V, G, G, G);break;case NONET:changeVisiable(G, G, G, G, V);break;case ERROR:changeVisiable(G, G, G, V, G);break;case EMPTY:changeVisiable(G, G, V, G, G);break;}}private void changeVisiable(final int contentStatus, final int loadStatus, final int emptyStatus, final int errorStatus, final int nonetStatus) {if (mContentView != null) {mContentView.setVisibility(contentStatus);}if (mLoadView != null) {mLoadView.setVisibility(loadStatus);}if (mEmptyView != null) {mEmptyView.setVisibility(emptyStatus);}if (mNoNetView != null) {mNoNetView.setVisibility(nonetStatus);}if (mErrorView != null) {mErrorView.setVisibility(errorStatus);}}@Overridepublic void onSuccess() {mMainThreadHandler.post(new Runnable() {@Overridepublic void run() {show(STATUS.SUCCESS);}});}@Overridepublic void onNoNet() {mMainThreadHandler.post(new Runnable() {@Overridepublic void run() {if (!isAddNoNet && mNoNetView != null) {mStatusContainer.addView(mNoNetView, mParams);isAddNoNet = true;}show(STATUS.NONET);}});}@Overridepublic void onError() {mMainThreadHandler.post(new Runnable() {@Overridepublic void run() {if (!isAddError && mErrorView != null) {mStatusContainer.addView(mErrorView, mParams);isAddError = true;}show(STATUS.ERROR);}});}@Overridepublic void onEmpty() {mMainThreadHandler.post(new Runnable() {@Overridepublic void run() {if (!isAddEmpty && mEmptyView != null) {mStatusContainer.addView(mEmptyView, mParams);isAddEmpty = true;}show(STATUS.EMPTY);}});}@Overridepublic void onClick(View view) {if (mOnRetryClick != null) {mOnRetryClick.onRetryLoad();}}public enum STATUS {LOADING,EMPTY,ERROR,SUCCESS,NONET}@Overridepublic void onDestory() {isAddNoNet = false;isAddEmpty = false;isAddLoad = false;isAddError = false;mContext = null;if (mLoadView != null) {mLoadView = null;}if (mContentView != null) {mContentView = null;}if (mEmptyView != null) {mEmptyView = null;}if (mErrorView != null) {mErrorView = null;}if (mNoNetView != null) {mNoNetView = null;}if (mParams != null) {mParams = null;}for (int i = 0; i
/**
- Created by AmatorLee on 2017/7/12. */
public abstract class StatusInterface {
protected abstract void initView();protected abstract void initContainer();protected abstract void onLoad();protected abstract void onSuccess();protected abstract void onNoNet();protected abstract void onError();protected abstract void onEmpty();protected abstract void onDestory();
}你可能会问为什么要提供一个
StatusInterface```,但是我不告诉你。 ####总结 现在流行的直播平台大都是这个小技巧,虽然简单但是常用,所有自己简单的写一下,如果你发现有bug,尽情反馈,同时我也会自我完善。 最后,provide a gayhub demo