編輯:關於android開發
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 @Override
102 public Class<User> 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<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
Android Studio導入github下載的project和module,androidgithub
Android Studio導入github下載的project和module,androidgithub前言:我們以前eclispe時代, 經常都是跑到github浏覽
Android Design Support Library——TabLayout,androidtablayout
Android Design Support Library——TabLayout,androidtablayout TabLayout——選項
Context是什麼,怎麼用,Context
Context是什麼,怎麼用,Context一.Context是什麼 官方文檔概述:關於應用程序環境的全局信息的接口。這是一個抽象類,它的實現是由安卓系統提供的。它允許訪
Android 貝塞爾曲線的淺析,android貝塞爾淺析
Android 貝塞爾曲線的淺析,android貝塞爾淺析博客也開了挺長時間了,一直都沒有來寫博客,主要原因是自己懶~~~此篇博客算是給2017年一個好的開始,同時也給2