android快速开发系列

项目基本框架搭架时的一些抽取:

其实任何应用就只有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;
	}
}
未完待续。。。。。。。。。。。 吐舌头 吐舌头

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值