项目基本框架搭架时的一些抽取:
其实任何应用就只有4种页面: 1.加载页面 2.错误页面 3.空页面 4.成功页面
对于前3种页面基本都是固定的, 属于常规页面, 而成功页面是需要根据实际情况做显示的.进入应用首先会显示加载页面, 在加载完数据之后, 才能判断出显示哪个具体页面.其实我们可以使用MVC模式来做控制, 现在M, V已经都有了, 那么还缺少一个C, 现在就开始动手吧, 我们准备创建类继承FrameLayout来作为控制类:
public abstract class LoadingPager extends FrameLayout {
private View mLoadingView;
private View mErrorView;
private View mEmptyView;
private View mSuccessView;
public static final int STATE_NONE = -1; // 默认状态
public static final int STATE_LOADING = 0; // 加载中
public static final int STATE_ERROR = 1; // 错误
public static final int STATE_EMPTY = 2; // 空
public static final int STATE_SUCCESS = 3; // 成功
public int mCurState = STATE_NONE;
public LoadingPager(Context context) {
super(context);
initCommonView();
}
/**
* @des 初始化常规视图① 加载页面② 错误页面③ 空页面
* @call LoadingPager初始化的时候被调用
*/
private void initCommonView() {
// ① 加载页面
mLoadingView = View.inflate(UIUtils.getContext(), R.layout.pager_loading, null);
this.addView(mLoadingView);
// ② 错误页面
mErrorView = View.inflate(UIUtils.getContext(), R.layout.pager_error, null);
this.addView(mErrorView);
// ③ 空页面
mEmptyView = View.inflate(UIUtils.getContext(), R.layout.pager_empty, null);
this.addView(mEmptyView);
refreshUIByState();
}
/**
* @des 根据当前的状态显示不同的视图
* @call 1.LoadingPager初始化的时候被调用
* @call 2.正在开始加载前,重置当前状态,会刷新ui
* @call 3.数据加载完成之后被调用
*/
private void refreshUIByState() {
// 控制加载页面的显示/隐藏
mLoadingView.setVisibility((mCurState == STATE_LOADING) || (mCurState == STATE_NONE) ? 0 : 8);
// 控制错误页面的显示/隐藏
mErrorView.setVisibility((mCurState == STATE_ERROR) ? 0 : 8);
// 控制空页面的显示/隐藏
mEmptyView.setVisibility((mCurState == STATE_EMPTY) ? 0 : 8);
if (mSuccessView == null && mCurState == STATE_SUCCESS) {
mSuccessView = initSuccessView();
this.addView(mSuccessView);
}
if (mSuccessView != null) {
// 控制成功页面的显示/隐藏
mSuccessView.setVisibility((mCurState == STATE_SUCCESS) ? 0 : 8);
}
}
// 数据加载的流程
/**
① 触发加载 进入页面开始加载/点击某一个按钮的时候加载
② 异步加载数据 -->显示加载视图
③ 处理加载结果
① 成功-->显示成功视图
② 失败
① 数据为空-->显示空视图
② 数据加载失败-->显示加载失败的视图
*/
// ① 触发加载
public void triggerLoadData() {
if (mCurState != STATE_SUCCESS && mCurState != STATE_LOADING) {
LogUtils.sf("###开始加载中");
// ② 异步加载数据
// 加载开始前,重置状态为加载中
int state = STATE_LOADING;
mCurState = state;
refreshUIByState();
// new Thread(new LoadDataTask()).start();
ThreadFactory.getNormalPool().execute(new LoadDataTask());
}
}
class LoadDataTask implements Runnable {
@Override
public void run() {// 子线程中
// 真正的开始加载数据
// 加载数据数据之后-->返回一个临时状态
int tempState = initData().getState();
// 临时状态==当前的状态
mCurState = tempState;
UIUtils.postTaskSafely(new Runnable() {
@Override
public void run() {
// 再次刷新视图显示
refreshUIByState();
}
});
}
}
/**
* @des 真正子子线程中加载数据,必须实现,但是不知道具体实现,交给子类去实现
* @call triggerLoadData方法被调用的时候调用
*/
protected abstract LoadedResult initData();
/**
* @des 数据加载成功的时候返回具体的成功视图,必须实现,但是不知道具体实现,交给子类实现
* @call 数据加载成功的时候
*/
protected abstract View initSuccessView();
public enum LoadedResult {
SUCCESS(STATE_SUCCESS), EMPTY(STATE_EMPTY), ERROR(STATE_ERROR);
int mState;
public int getState() {
return mState;
}
private LoadedResult(int state) {
mState = state;
}
}
}
OK, 我再贴上BaseFragment的代码, 我们可以创建子类来完成具体的显示:
public abstract class BaseFragment extends Fragment {
private LoadingPager mLoadingPager;
public LoadingPager getLoadingPager() {
return mLoadingPager;
}
@Override
public boolean getUserVisibleHint() {// 类似我们fragment里面的onresume
/*
mLoadingPager.triggerLoadData();
*/
return super.getUserVisibleHint();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (mLoadingPager == null) {// 第一次
mLoadingPager = new LoadingPager(UIUtils.getContext()) {
@Override
protected LoadedResult initData() {
return BaseFragment.this.initData();
}
@Override
protected View initSuccessView() {
return BaseFragment.this.initSuccessView();
}
};
} else {// 第2次
ViewParent parent = mLoadingPager.getParent();
if (parent != null && parent instanceof ViewGroup) {
((ViewGroup) parent).removeView(mLoadingPager);
}
}
// 盒子里面的一个BaseFragment取出来-->取出里面的mLoadingPager-->返回给viewPager-->adapter-->Fragment
return mLoadingPager;// -->view-->ViewGroup
}
// 页面显示分析
// Fragment/Activity共性-->页面共性-->视图的展示
/**
任何应用其实就只有4种页面类型-->常规的页面
① 加载页面
② 错误页面
③ 空页面
④ 成功页面
①②③三种页面一个应用基本是固定的
每一个fragment/activity对应的页面④就不一样
进入应用的时候显示①,②③④需要加载数据之后才知道显示哪个
*/
// 数据加载的流程
/**
① 触发加载 进入页面开始加载/点击某一个按钮的时候加载
② 异步加载数据 -->显示加载视图
③ 处理加载结果
① 成功-->显示成功视图
② 失败
① 数据为空-->显示空视图
② 数据加载失败-->显示加载失败的视图
*/
/**
* @des 真正子子线程中加载数据,必须实现,但是不知道具体实现,交给子类去实现
* @des 它是和LoadingPager中的initData同名方法
* @call triggerLoadData方法被调用的时候调用
*/
protected abstract LoadedResult initData();
/**
* @des 数据加载成功的时候返回具体的成功视图,必须实现,但是不知道具体实现,交给子类实现
* @des 它是和LoadingPager中的initSuccessView同名方法
* @call 数据加载成功的时候
*/
protected abstract View initSuccessView();
/**
* 检测加载网络之后返回数据对应的状态
* @param obj
* @return
*/
public LoadedResult checkState(Object obj) {
if (obj == null) {
return LoadedResult.EMPTY;
}
// list
if (obj instanceof List) {
if (((List) obj).size() == 0) {
return LoadedResult.EMPTY;
}
}
// map
if (obj instanceof Map) {
if (((Map) obj).size() == 0) {
return LoadedResult.EMPTY;
}
}
return LoadedResult.SUCCESS;
}
}
未完待续。。。。。。。。。。。