一,概述
这是高仿goole市场的一个项目。配有服务端。这里我们只关注客户端。由于优快云对图片大小有限制,有的功能没演示出来。后续会一点点的贴出。基本效果如下:
二,分析
和市场上很多项目整体模式一样。ViewPagerIndictor+ViewPager+Fragment。每个Fragment有个共同的特点:都需要加载数据,且都需要展示出来。那么就可以抽取出来一个基类,LoadFragment。每个Fragment展示出来的UI有四种(加载数据UI,失败UI,服务器未给数据UI,成功UI):
共同点
- 加载数据UI
- 失败的UI
- 服务器未给数据UI
不同点:
- 数据成功UI
四种展示的UI可以通过自定义ViewGroup来管理实现(LoadUi)。LoadUI并不知道每个数据成功UI是什么样子,且基类LoadFragment也不知道。每个Fragment的成功UI是不同的。所以延迟到子类具体实现。
1.LoadUI有五种状态以及上面提到的四种UI:
- 空状态
- 加载中状态
- 加载失败状态
- 加载为空状态
- 加载成功状态
public final static int STATE_NONE = 0;
public final static int STATE_LOADING = 1;
public final static int STATE_EMPTY = 2;
public final static int STATE_ERROR = 3;
public final static int STATE_SUCCESS = 4;
四种UI
private View mLoadingView;
private View mErrorView;
private View mEmptyView;
private View mSuccessView;
2.LoadUI的行为是:加载数据,根据加载返回来状态来显示更新UI
但LoadUi不清楚具体是怎么样加载数据的,Fragment也不清楚。和成功UI一样,具体实现延迟到子类。
private class LoadDataTask implements Runnable {
@Override
public void run() {
SystemClock.sleep(3000);//模拟加载耗时操作
Result result = onLoadData();
mCurruntState = result.getState();
safeUpdateUI();
}
}
private void safeUpdateUI() {
UIUtils.getMainHandler().post(new Runnable() {
@Override
public void run() {
updateUI();
}
});
}
protected abstract View onLoadSuccessView();
protected abstract Result onLoadData();
前面提到了LoadFragment不知道每个子Fragment的成功UI是什么样子。也不知道每个子Fragment是如何具体加载数据的。所以都延迟到子类去实现。
protected abstract View startLoadSuccessView();
protected abstract LoadUi.Result startLoadUI();
三,类图
四,细节的处理
通过FragmentFractory对Fragment集中管理,避免创建过多的对象。用了Google SparseArrayCompat取代HashMap
package com.yp2019cl.googlemarket.fragment;
import android.support.v4.util.SparseArrayCompat;
import com.yp2019cl.googlemarket.base.LoadFragment;
/**
* @项目名: GoogleMarket
* @包名: com.yp2019cl.googlemarket.fragment
* @类名: FragmentFractory
* @作者: yp
* @创建时间: 2016/03/17 23:12
* @描述: TODO:
*/
public class FragmentFractory {
private static SparseArrayCompat<LoadFragment> mCaches = new SparseArrayCompat<LoadFragment>();
private static LoadFragment mFragment;
public static LoadFragment getFragment(int position) {
mFragment = mCaches.get(position);
if (mFragment != null) {
return mFragment;
}
switch (position) {
case 0:
mFragment = new HomeFragment();
break;
case 1:
mFragment = new AppFragment();
break;
case 2:
mFragment = new GameFragment();
break;
case 3:
mFragment = new SubFragment();
break;
case 4:
mFragment = new RecommendFragment();
break;
case 5:
mFragment = new CategoryFragment();
break;
case 6:
mFragment = new HomeFragment();
break;
}
mCaches.put(position, mFragment);
return mFragment;
}
}
PagerAdapter getItem代码:
@Override
public Fragment getItem(int position) {
return FragmentFractory.getFragment(position);
}