楼主5月份就已经来北京这边找工作了,本来以为堂堂天朝的帝都开发水平秒杀我们这些偏远地区的渣渣,但是在这边工作了几个月发现那其实只是少数情况,
不管作为一个什么样的app,下拉刷新的功能基本都是比不可少的,但是换了两家公司发现,一个非常牛逼的公司开发的app竟然都没有人封装这个功能,
作为一个程序猿你这么写代码真是越来越退化了, 不瞎扯了,上正题
本文只是为了封装下拉刷新功能,所以没有讲究现在到底用哪种下拉刷新控件比较好,我选的是以前项目中使用的XListView ,
为了方便 在每一个activity或者fragment 中控制页数,我在XListView 中添加了几个方法
public static final int FIRST_PAGE=1;开始也的页数标签,可能是第1页,也可能是0页
public int nextPage(){ page++; return page; } public void resetPage(){ page=FIRST_PAGE; } public int currentPage(){ return page; } public void privoidsPage(){ if(page==FIRST_PAGE) return; page--; }这样的话在使用的时候直接调用 xlv.nextPage() 就可以方便的下一页了,省时省力还省心...
为了更好的约束下拉刷新时具体涉及到哪些方法,我定义了一个接口类,需要实现的功能尽收眼底
因为每次加载的数据不一定,所以这里面我用了泛型
public interface RefreshLoader<T> { 加载完成 是否成功 如果成功则页数不会退 // 如果失败则页数回退 如果当前页数为0 则页数回退为0 void onLoadFinish(boolean success,List<T> list); 上拉更新 void onLoadNextPage(); ///下拉刷新 void onLoadFirstPage(); 通过sp 读取数据 List<T> readList(); 清除sp中的该类型列表 void clearList(); 保存sp中该类型列表 void saveList(List<T> list); ///每一页缓存数据的个数 int pageCount(); }
下面就是主要的代码了,基本没有什么逻辑,
public abstract class BaseCacheActivity<T> extends AppCompatActivity implements RefreshLoader<T> { public static final int TOP_MODEL = 1; public static final int BOTTOM_MDOEL = 2; public static final int BOTH = TOP_MODEL | BOTTOM_MDOEL; private XListView lv_list; private TsmBaseAdapter<T> adapter; protected int model; private CustomProgressDialog loadingdialog; private EmptyView empty_view; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { ActionBar bar = this.getSupportActionBar(); bar.hide(); lv_list = (XListView) findViewById(R.id.lv_test); ViewStub vs_empty = (ViewStub) findViewById(R.id.vs_empty); vs_empty.inflate(); View view = findViewById(R.id.inflate_id); lv_list.setEmptyView(view); empty_view = (EmptyView) view.findViewById(R.id.empty_view); empty_view.setEmptyBtnClickListeners(new EmptyView.EmptyBtnClickListeners() { @Override public void onClick() { showLoadingDialog(); lv_list.resetPage(); onLoadDate(lv_list.currentPage(), pageCount()); } }); } /** * 初始化下拉刷新 由子类调用, * * @param model * @param adapter */ public void initLoader(int model, final TsmBaseAdapter<T> adapter) { this.model = model; this.adapter = adapter; lv_list.setPullRefreshEnable(isTopCanRefresh()); lv_list.setPullLoadEnable(isBottemRefresh()); lv_list.setAdapter(adapter); lv_list.setXListViewListener(new XListView.IXListViewListener() { @Override public void onRefresh() { showLoadingDialog(); onLoadFirstPage(); } @Override public void onLoadMore() { showLoadingDialog(); onLoadNextPage(); } }); initDate(); } /** * 初始数据,为空显示加载dialog并加载 * 不为空静默加载 */ private void initDate() { List<T> list = this.readList(); if (list == null || list.size() == 0) { showLoadingDialog();///显示加载框 } this.adapter.setList(list); lv_list.resetPage(); this.onLoadDate(lv_list.currentPage(), pageCount()); } /** * 显示加载进度框 */ private void showLoadingDialog() { if (loadingdialog == null) loadingdialog = CustomProgressDialog.createDialog(this, true); if (!loadingdialog.isShowing()) loadingdialog.show(); } /** * 隐藏加载进度框 */ private void hideLoadingDialog() { if (loadingdialog == null) return; if (loadingdialog.isShowing()) loadingdialog.dismiss(); } /** * 是否可以下拉刷新 * * @return */ public boolean isTopCanRefresh() { return (this.model & TOP_MODEL) > 0; } /** * 是否可以下拉加载 * * @return */ public boolean isBottemRefresh() { return (this.model & BOTTOM_MDOEL) > 0; } /** * 加载数据方法 抽象方法 * 子类必须自己实现, 通过不同的接口返回不同类型的数据 * @param page * @param pageCount */ public abstract void onLoadDate(int page, int pageCount); /** * 刷新完成 * * @param success 是否成功 * @param list 返回的列表 */ @Override public void onLoadFinish(boolean success, List<T> list) { lv_list.stopRefresh(); lv_list.stopLoadMore(); hideLoadingDialog(); if (lv_list.currentPage() == XListView.FIRST_PAGE) { /** * 只有在加载失败并且没有网的情况下 * 设置emptyview 为 没有网装填 * 其他设置为空数据状态 * */ if (!success && !Utils.hasNetWork()) { empty_view.setImage(R.mipmap.meiwang); } else{ empty_view.setImage(R.mipmap.meishuju); } adapter.setList(list); } else { adapter.addList(list); } if (!success) lv_list.privoidsPage(); } /** * 上啦更新 */ @Override public void onLoadNextPage() { lv_list.nextPage(); onLoadDate(lv_list.currentPage(), pageCount()); } /** * 下拉刷新 */ @Override public void onLoadFirstPage() { lv_list.resetPage(); onLoadDate(lv_list.currentPage(), pageCount()); } /** * 从sp中获取数据 * 静默刷新 * * @return */ @Override public List<T> readList() { Class<?> cls = this.getModelClass(); if (cls == null) return null; String json = AppConfig.getInstance(this).getString(this, cls.getSimpleName()); if (Utils.isEmpty(json)) return null; List<T> list = (List<T>) GsonUtil.getList(json, cls); return list; } /** * 获取缓存的数据类型 * * @return */ public Class<?> getModelClass() { return null; } /** * 清除sp的该列表的数据 */ @Override public void clearList() { Class<?> cls = getModelClass(); if (cls == null) return; AppConfig.getInstance(this).putString(this, cls.getSimpleName(), ""); } /** * 将列表保存到sp中 * 只保存下路刷新时候的数据 * * @param list */ @Override public void saveList(List<T> list) { Class<?> cls = getModelClass(); if (cls == null) { return; } if (list == null) { AppConfig.getInstance(this).putString(this, cls.getSimpleName(), ""); return; } String json = GsonUtil.G.toJson(list); AppConfig.getInstance(this).putString(this, cls.getSimpleName(), json); } /** * 页面结束保存数据 */ @Override protected void onDestroy() { saveList(adapter.getList()); super.onDestroy(); } /** * 每页缓存的数据 * * @return */ @Override public int pageCount() { return 10; } }
最后是mainactivity的代码 哈哈 是不是很简洁
public class MainActivity extends BaseCacheActivity<EmptyBean> { private MyAdapter adapter; private Handler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); adapter=new MyAdapter(this,null); handler=new Handler(); initLoader(BaseCacheActivity.BOTH,adapter); } @Override public void onLoadDate(int page, int pageCount) { Log.i("info","---------------onLoadDate--------------page:"+page); handler.postDelayed(new Runnable() { @Override public void run() { int a = new Random().nextInt(10); onLoadFinish(a>5,a>5?newshuju():null); } },2000); }
/** * 获取缓存的数据类型 *如果不重写该方法,则本地不会保存数据 * @return */ public Class<?> getModelClass() { return null; } /** * 清除sp的该列表的数据 */ @Override public void clearList() { Class<?> cls = getModelClass(); if (cls == null) return; AppConfig.getInstance(this).putString(this, cls.getSimpleName(), ""); } /** * 将列表保存到sp中 * 只保存下路刷新时候的数据 * * @param list */ @Override public void saveList(List<T> list) { Class<?> cls = getModelClass(); if (cls == null) { return; } if (list == null) { AppConfig.getInstance(this).putString(this, cls.getSimpleName(), ""); return; } String json = GsonUtil.G.toJson(list); AppConfig.getInstance(this).putString(this, cls.getSimpleName(), json); } /** * 页面结束保存数据 */ @Override protected void onDestroy() { saveList(adapter.getList()); super.onDestroy(); } /** * 每页缓存的数据 * * @return */ @Override public int pageCount() { return 10; }
由于获取网络状态和加载数据是否成功我都使用的随机数判断的返回状态,所以在下拉刷新或者上拉更新的过程所有可能都会交替出现,
千万不要认为楼主写的代码有bug (-->_<--)!!!
最后附上demo源码 http://download.csdn.net/detail/qq_22256027/9665492