原來Activity和Fragment中實現同樣功能的上千行代碼竟然能簡化成100多行!!! 而且如果是Fragment,有一個XListView預設佈局,連layout都不再需要寫了!!! ...
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
下載試用