BaseHttpListActivity,几行代码搞定Android Http列表请求、加载和缓存

Stella981
• 阅读 436

Android开发中,向服务器请求一个列表并显示是非常常见的需求,但实现起来比较麻烦,代码繁杂。

随着应用的更新迭代,这种需求越来越多,我渐渐发现了实现这种需求的代码的共同点。

于是我将Activity中http列表请求和加载的相同功能代码提取出来,作为这种Activity的基类,名为BaseHttpListActivity。

之后将缓存功能也集成在BaseHttpListActivity中,然后还根据业务需求衍生出了BaseHttpListFragment。

后来又有了从本地数据库加载列表的需求,就再次从BaseHttpListActivity提取出了BaseListActivity,负责列表显示和缓存。

BaseHttpListActivity只负责http请求,通过继承BaseHttpListActivity来实现显示和缓存。

有了BaseHttpListActivity和BaseHttpListFragment,原来用于实现http列表请求、加载和缓存的代码就变得非常简单了。

比如以下这个界面的主页:

BaseHttpListActivity,几行代码搞定Android Http列表请求、加载和缓存

列表是一个UserListFragment,支持下拉刷新上拉加载,第一次进入会直接显示刷新动画并加载数据。

1 /**用户列表界面fragment 2 * @author Lemon 3 * @use new UserListFragment(),详细使用见.DemoFragmentActivity(initData方法内) 4 * @must 查看 .HttpManager 中的@must和@warn 5 * 查看 .SettingUtil 中的@must和@warn 6 */ 7 public class UserListFragment extends BaseHttpListFragment<User, UserAdapter> 8 implements OnItemClickListener, OnCacheCallBack { 9 // private static final String TAG = "UserListFragment"; 10 11 //与Activity通信<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 12 13 public static final String ARGUMENT_RANGE = "ARGUMENT_RANGE"; 14 15 //与Activity通信>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 16 17 18 public static final int RANGE_ALL = HttpRequest.USER_LIST_RANGE_ALL; 19 public static final int RANGE_RECOMMEND = HttpRequest.USER_LIST_RANGE_RECOMMEND; 20 21 private int range = RANGE_ALL; 22 @Override 23 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 24 super.onCreateView(inflater, container, savedInstanceState); 25 26 argument = getArguments(); 27 if (argument != null) { 28 range = argument.getInt(ARGUMENT_RANGE, range); 29 } 30 31 32 initCache(this); 33 34 //功能归类分区方法,必须调用<<<<<<<<<< 35 initView(); 36 initData(); 37 initListener(); 38 //功能归类分区方法,必须调用>>>>>>>>>> 39 40 lvBaseList.onRefresh(); 41 42 return view; 43 } 44 45 46 //UI显示区(操作UI,但不存在数据获取或处理代码,也不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 47 48 @Override 49 public void initView() {//必须调用 50 super.initView(); 51 52 } 53 54 @Override 55 public void setList(final List list) { 56 setList(list, new AdapterCallBack() { 57 58 @Override 59 public void refreshAdapter() { 60 adapter.refresh(list); 61 } 62
63 @Override 64 public UserAdapter createAdapter() { 65 return new UserAdapter(context, list); 66 } 67 }); 68 } 69 70 71 72 //UI显示区(操作UI,但不存在数据获取或处理代码,也不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 73 74 75 76 77 78 79 80 81 82 83 //data数据区(存在数据获取或处理代码,但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 84 85 @Override 86 public void initData() {//必须调用 87 super.initData(); 88 89 } 90 91 @Override 92 public void getListAsync(final int pageNum) { 93 HttpRequest.getUserList(range, pageNum, 0, this); 94 } 95 96 @Override 97 public List parseArray(String json) { 98 return Json.parseArray(json, User.class); 99 } 100 101 @Override 102 public Class getCacheClass() { 103 return User.class; 104 } 105 @Override 106 public String getCacheGroup() { 107 return "range=" + range; 108 } 109 @Override 110 public String getCacheId(User data) { 111 return data == null ? null : "" + data.getId(); 112 } 113 114 115 116 //data数据区(存在数据获取或处理代码,但不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 117 118 119 120 121 122 123 124 125 //listener事件监听区(只要存在事件监听代码就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 126 127 128 @Override 129 public void initListener() {//必须调用 130 super.initListener(); 131 132 lvBaseList.setOnItemClickListener(this); 133 } 134 135 136 137 //系统自带监听方法 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 138 139 @Override 140 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 141 position -= lvBaseList.getHeaderViewsCount(); 142 if (position < 0 || adapter == null || position >= adapter.getCount()) { 143 return; 144 } 145 146 User user = adapter.getItem(position); 147 if (BaseModel.isCorrect(user)) {//相当于 user != null && user.getId() > 0 148 toActivity(UserActivity.createIntent(context, user.getId())); 149 } 150 } 151 152 153 //类相关监听<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 154 155 156 //类相关监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 157 158 159 160 //系统自带监听方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 161 162 163 //listener事件监听区(只要存在事件监听代码就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 164 165 166 167 168 169 170 171 172 //内部类,尽量少用<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 173 174 175 //内部类,尽量少用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 176 177 178 }

getListAsync用于请求服务器列表数据,setList用于显示列表数据,

parseArray用于将服务器返回的json串转化为一个List的方法。

通过initCache(this);初始化缓存,得到getCacheClass,getCacheGroup,getCacheId这3个缓存方法。

range相关代码是为了传入一个用户范围(或类型),让服务器返回需要范围的数据。

listener事件监听区代码里实现了点击列表项跳转至用户详情界面的功能。

剩下onCreateView和3个init方法维持着这个Fragment的框架。

原来Activity和Fragment中实现同样功能的上千行代码竟然能简化成这样!!!

而且如果是Fragment,有一个XListView默认布局,连layout都不再需要写了!!!

如果只需要从服务器加载一个列表,缓存和事件相关代码就可以去掉了;如果不需要限定数据范围,还可以去掉range相关代码。

1 /**用户列表界面fragment 2 * @author Lemon 3 * @use new UserListFragment(),详细使用见.DemoFragmentActivity(initData方法内) 4 * @must 查看 .HttpManager 中的@must和@warn 5 * 查看 .SettingUtil 中的@must和@warn 6 */ 7 public class UserListFragment extends BaseHttpListFragment<User, UserAdapter> { 8 // private static final String TAG = "UserListFragment"; 9 10 @Override 11 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 12 super.onCreateView(inflater, container, savedInstanceState); 13 14 //功能归类分区方法,必须调用<<<<<<<<<< 15 initView(); 16 initData(); 17 initListener(); 18 //功能归类分区方法,必须调用>>>>>>>>>> 19 20 lvBaseList.onRefresh(); 21 22 return view; 23 } 24 25 26 //UI显示区(操作UI,但不存在数据获取或处理代码,也不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 27 28 @Override 29 public void setList(final List list) { 30 setList(list, new AdapterCallBack() { 31 32 @Override 33 public void refreshAdapter() { 34 adapter.refresh(list); 35 } 36
37 @Override 38 public UserAdapter createAdapter() { 39 return new UserAdapter(context, list); 40 } 41 }); 42 } 43 44 45 46 //UI显示区(操作UI,但不存在数据获取或处理代码,也不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 47 48 49 50 51 52 53 54 55 56 57 //data数据区(存在数据获取或处理代码,但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 58 59 @Override 60 public void getListAsync(final int pageNum) { 61 HttpRequest.getUserList(0, pageNum, 0, this); 62 } 63 64 @Override 65 public List parseArray(String json) { 66 return Json.parseArray(json, User.class); 67 } 68 69 70 //data数据区(存在数据获取或处理代码,但不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 71 72 73 74 75 76 77 78 79 //listener事件监听区(只要存在事件监听代码就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 80 81 82 83 //类相关监听<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 84 85 86 //类相关监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 87 88 89 90 //系统自带监听方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 91 92 93 //listener事件监听区(只要存在事件监听代码就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 94 95 96 97 98 99 100 101 102 //内部类,尽量少用<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 103 104 105 //内部类,尽量少用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 106 107 108 }

是不是更简洁了呢?

BaseHttpListActivity和BaseHttpListFragment已开源,依赖ZBLibrary(含使用方法)就可使用,下方附下载地址。

ZBLibrary-Android快速开发框架

BaseHttpListActivity,几行代码搞定Android Http列表请求、加载和缓存

下载地址(欢迎Star,欢迎Fork)

https://github.com/TommyLemon/Android-ZBLibrary

下载试用

ZBLibraryDemoApp.apk

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Souleigh ✨ Souleigh ✨
3年前
前端性能优化 - 雅虎军规
无论是在工作中,还是在面试中,web前端性能的优化都是很重要的,那么我们进行优化需要从哪些方面入手呢?可以遵循雅虎的前端优化35条军规,这样对于优化有一个比较清晰的方向.35条军规1.尽量减少HTTP请求个数——须权衡2.使用CDN(内容分发网络)3.为文件头指定Expires或CacheControl,使内容具有缓存性。4.避免空的
Stella981 Stella981
3年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
35岁是技术人的天花板吗?
35岁是技术人的天花板吗?我非常不认同“35岁现象”,人类没有那么脆弱,人类的智力不会说是35岁之后就停止发展,更不是说35岁之后就没有机会了。马云35岁还在教书,任正非35岁还在工厂上班。为什么技术人员到35岁就应该退役了呢?所以35岁根本就不是一个问题,我今年已经37岁了,我发现我才刚刚找到自己的节奏,刚刚上路。
Python进阶者 Python进阶者
9个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这