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 { 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快速开发框架
下载地址(欢迎Star,欢迎Fork)
https://github.com/TommyLemon/Android-ZBLibrary
下载试用
ZBLibraryDemoApp.apk