你的位置:首页 > 操作系统

[操作系统]BaseHttpListActivity,几行代码搞定Android Http列表请求、加载和缓存


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

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

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

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

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

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

 

有了BaseHttpListActivity和BaseHttpListFragment,原来用于实现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<User> { 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<User> list) { 56     setList(list, new AdapterCallBack<UserAdapter>() { 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<User> parseArray(String json) { 98     return Json.parseArray(json, User.class); 99   }100 101   @Override102   public Class<User> getCacheClass() {103     return User.class;104   }105   @Override106   public String getCacheGroup() {107     return "range=" + range;108   }109   @Override110   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   @Override129   public void initListener() {//必须调用130     super.initListener();131 132     lvBaseList.setOnItemClickListener(this);133   }134 135 136 137   //系统自带监听方法 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<138 139   @Override140   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() > 0148       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<User>的方法。

通过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<User> list) { 30     setList(list, new AdapterCallBack<UserAdapter>() { 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<User> 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快速开发框架

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

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

下载试用

ZBLibraryDemoApp.apk