BaseHttpListActivity,幾行代碼搞定Android Http列表請求、載入和緩存

来源:http://www.cnblogs.com/LemonStantard/archive/2016/08/03/5719477.html
-Advertisement-
Play Games

原來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

下載試用

ZBLibraryDemoApp.apk


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一個APP的需求來自於哪兒?產品、老闆、客戶….. 做程式員不容易,需求一句話,就是幾千幾萬行代碼!所幸,在AppCan平臺開發APP,開發者只需完成應用的前端部分,至於各項複雜的功能,就交給AppCan來搞定吧! ...
  • 最近項目中經常有遇到從伺服器請求的數據是null的情況,這種情況下如果用[dic objectForKey:@"key"]方法,程式會發生崩潰現象,因為項目是以前的老項目,而且有太多個這樣的方法,於是想起了前幾天的runtime知識,嘗試簡單的實現了一個交換方法。 1.首先實現了一個字典的分類。 2 ...
  • 1:iOS SEL的簡單總結 SEL就是對方法的一種包裝。包裝的SEL類型數據它對應相應的方法地址,找到方法地址就可以調用方法 a.方法的存儲位置 在記憶體中每個類的方法都存儲在類對象中 每個方法都有一個與之對應的SEL類型的數據 根據一個SEL數據就可以找到對應的方法地址,進而調用方法 SEL類型的 ...
  • Mobile What to Expect From Swift 3 Web A practical security guide for web developers Gulp Succinctly – free book Running Node.js on Linux With systemd... ...
  • 文件下載主要代碼也不多,使用原生的DownloadManage來實現該功能: AndroidManifest中添加許可權 <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:na ...
  • 寫的例子比較簡單,是用xutils3.0來進行下載項目更新 1.先通過網路請求,判斷版本是否要更新 2.若要更新,則彈出一個彈窗,我用的是系統自帶的Dialog,將下載的版本號及下載的內容提示展示出來 3.當用戶點擊下載時,開始下載,下載時展示一個水平的進度條 4.下載完成後,進度條消失,調用系統安 ...
  • NSDate * senddate=[NSDate date]; NSDateFormatter *dateformatter=[[NSDateFormatter alloc] init]; [dateformatter setDateFormat:@"YYYYMMdd"]; NSString * ...
  • ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...