Android AsyncTask 詳解及註意事項

来源:http://www.cnblogs.com/Linccy/archive/2016/07/07/5648540.html
-Advertisement-
Play Games

AsyncTask定義了三種泛型類型 Params,Progress和Result。 Params 啟動任務執行的輸入參數,比如HTTP請求的URL。 Progress 後臺任務執行的百分比。 Result 後臺執行任務最終返回的結果,比如String。 Params 啟動任務執行的輸入參數,比如H ...


AsyncTask是Android提供的輕量級的非同步類,它使創建非同步任務變得更加簡單,不再需要編寫任務線程和Handler實例即可完成相同的任務。

AsyncTask定義了三種泛型類型 Params,Progress和Result。

  • Params 啟動任務執行的輸入參數,比如HTTP請求的URL。
  • Progress 後臺任務執行的百分比。
  • Result 後臺執行任務最終返回的結果,比如String。
例如:
class RetrieveCategoryTask extends AsyncTask<String, Void, List<String>>

根據AsyncTask源碼:

public abstract class AsyncTask<Params, Progress, Result> 

這裡的String, Void, List<String>分別對應Params, Progress, Result



一般使用AsyncTask至少需要實現以下2個方法:
protected abstract Result doInBackground(Params... var1);//耗時操作,例如網路請求任務。這裡相當於一個子線程
   protected void onPostExecute(Result result) {//可以在這裡處理doInBackground得到的數據,能夠對UI進行操作,屬於UI主線程
        throw new RuntimeException("Stub!");
    }

當然如果有必要的話還可以實現下麵幾個方法:

  • onProgressUpdate(Progress…)   可以使用進度條增加用戶體驗度。 此方法在主線程執行,用於顯示任務執行的進度。
  • onPreExecute()        這裡是最終用戶調用Excute時的介面,當任務執行之前開始調用此方法,可以在這裡顯示進度對話框。
  • onCancelled()             用戶調用取消時,會調用此方法

使用AsyncTask類,以下是幾條必須遵守的準則:

  • Task的實例必須在UI thread中創建;
  • execute方法必須在UI thread中調用;
  • 不要手動的調用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)這幾個方法;
  • 該task只能被執行一次,否則多次調用時將會出現異常;

 

需要註意的是Android為了安全考慮,不允許在主線程即UI線程進行耗時操作。例如HTTP請求等。

如果在UI中使用了耗時操作的話,Android Studio本身是不會報錯的。只有在APP執行到相應的耗時操作位置時才會停止運行。手機或模擬器上會出現“很抱歉,XXX已停止運行”同時Android Studio logcat輸出“

E/AndroidRuntime: FATAL EXCEPTION: main
Process:.....

 java.lang.RuntimeException.....

下麵給出一個範例:

  1 package idv.ron.texttojson_android;
  2 
  3 import android.app.ProgressDialog;
  4 import android.content.Context;
  5 import android.net.ConnectivityManager;
  6 import android.net.NetworkInfo;
  7 import android.os.AsyncTask;
  8 import android.os.Bundle;
  9 import android.support.v7.app.ActionBarActivity;
 10 import android.util.Log;
 11 import android.view.LayoutInflater;
 12 import android.view.View;
 13 import android.view.ViewGroup;
 14 import android.widget.AdapterView;
 15 import android.widget.AdapterView.OnItemClickListener;
 16 import android.widget.ArrayAdapter;
 17 import android.widget.BaseAdapter;
 18 import android.widget.ListView;
 19 import android.widget.Spinner;
 20 import android.widget.TextView;
 21 import android.widget.Toast;
 22 
 23 import com.google.gson.Gson;
 24 import com.google.gson.JsonObject;
 25 import com.google.gson.reflect.TypeToken;
 26 
 27 import java.io.BufferedReader;
 28 import java.io.BufferedWriter;
 29 import java.io.IOException;
 30 import java.io.InputStreamReader;
 31 import java.io.OutputStreamWriter;
 32 import java.lang.reflect.Type;
 33 import java.net.HttpURLConnection;
 34 import java.net.URL;
 35 import java.util.List;
 36 
 37 public class SearchActivity extends ActionBarActivity {
 38     private final static String TAG = "SearchActivity";
 39     private ProgressDialog progressDialog;
 40     private AsyncTask retrieveCategoryTask, retrieveBookTask;
 41     private Spinner spCategory;
 42     private ListView lvBook;
 43 
 44     class RetrieveCategoryTask extends AsyncTask<String, Void, List<String>> {
 45         @Override
 46         protected void onPreExecute() {
 47             super.onPreExecute();
 48             progressDialog = new ProgressDialog(SearchActivity.this);
 49             progressDialog.setMessage("Loading...");
 50             progressDialog.show();
 51         }
 52 
 53         @Override
 54         protected List<String> doInBackground(String... params) {
 55             String url = params[0];
 56             String jsonIn;
 57             JsonObject jsonObject = new JsonObject();
 58             jsonObject.addProperty("param", "category");
 59             try {
 60                 jsonIn = getRemoteData(url, jsonObject.toString());
 61             } catch (IOException e) {
 62                 Log.e(TAG, e.toString());
 63                 return null;
 64             }
 65 
 66             Gson gson = new Gson();
 67             Type listType = new TypeToken<List<String>>() {
 68             }.getType();
 69 
 70             return gson.fromJson(jsonIn, listType);
 71         }
 72 
 73         @Override
 74         protected void onPostExecute(List<String> items) {
 75             ArrayAdapter<String> adapter = new ArrayAdapter<>(SearchActivity.this,
 76                     android.R.layout.simple_list_item_1, items);
 77             adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
 78             spCategory.setAdapter(adapter);
 79             progressDialog.cancel();
 80         }
 81     }
 82 
 83     public class RetrieveBookTask extends
 84             AsyncTask<String, Integer, List<Book>> {
 85         @Override
 86         protected void onPreExecute() {
 87             super.onPreExecute();
 88             progressDialog = new ProgressDialog(SearchActivity.this);
 89             progressDialog.setMessage("Loading...");
 90             progressDialog.show();
 91         }
 92 
 93         @Override
 94         protected List<Book> doInBackground(String... params) {
 95             String url = params[0];
 96             String category = params[1];
 97             String jsonIn;
 98             JsonObject jsonObject = new JsonObject();
 99             jsonObject.addProperty("param", category);
100             try {
101                 jsonIn = getRemoteData(url, jsonObject.toString());
102             } catch (IOException e) {
103                 Log.e(TAG, e.toString());
104                 return null;
105             }
106 
107             Gson gson = new Gson();
108             Type listType = new TypeToken<List<Book>>() {
109             }.getType();
110             return gson.fromJson(jsonIn, listType);
111         }
112 
113         @Override
114         protected void onPostExecute(List<Book> result) {
115             showResult(result);
116             progressDialog.cancel();
117         }
118     }
119 
120     @Override
121     protected void onCreate(Bundle savedInstanceState) {
122         super.onCreate(savedInstanceState);
123         setContentView(R.layout.search_activity);
124         spCategory = (Spinner) findViewById(R.id.spCategory);
125         lvBook = (ListView) findViewById(R.id.lvBook);
126         if (networkConnected()) {
127             retrieveCategoryTask = new RetrieveCategoryTask().execute(Common.URL);
128         } else {
129             showToast(this, R.string.msg_NoNetwork);
130         }
131     }
132 
133     // check if the device connect to the network
134     private boolean networkConnected() {
135         ConnectivityManager conManager =
136                 (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
137         NetworkInfo networkInfo = conManager.getActiveNetworkInfo();
138         return networkInfo != null && networkInfo.isConnected();
139     }
140 
141 
142     private String getRemoteData(String url, String jsonOut) throws IOException {
143         StringBuilder jsonIn = new StringBuilder();
144         HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
145         connection.setDoInput(true); // allow inputs
146         connection.setDoOutput(true); // allow outputs
147         connection.setUseCaches(false); // do not use a cached copy
148         connection.setRequestMethod("POST");
149         connection.setRequestProperty("charset", "UTF-8");
150         BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));
151         bw.write(jsonOut);
152         Log.d(TAG, "jsonOut: " + jsonOut);
153         bw.close();
154 
155         int responseCode = connection.getResponseCode();
156 
157         if (responseCode == 200) {
158             BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
159             String line;
160             while ((line = br.readLine()) != null) {
161                 jsonIn.append(line);
162             }
163         } else {
164             Log.d(TAG, "response code: " + responseCode);
165         }
166         connection.disconnect();
167         Log.d(TAG, "jsonIn: " + jsonIn);
168         return jsonIn.toString();
169     }
170 
171     public void onSearchClick(View v) {
172         Object item = spCategory.getSelectedItem();
173         if (item == null || item.toString().trim().length() <= 0) {
174             showToast(this, R.string.msg_NoCategoryFound);
175         } else {
176             String category = item.toString().trim();
177             if (networkConnected()) {
178                 retrieveBookTask = new RetrieveBookTask().execute(Common.URL, category);
179             } else {
180                 showToast(this, R.string.msg_NoNetwork);
181             }
182         }
183     }
184 
185     public void showResult(List<Book> result) {
186         final BookListAdapter adapter = new BookListAdapter(this, result);
187         lvBook.setAdapter(adapter);
188         lvBook.setOnItemClickListener(new OnItemClickListener() {
189             @Override
190             public void onItemClick(AdapterView<?> parent, View view,
191                                     int position, long id) {
192                 adapter.expand(position);
193                 lvBook.setItemChecked(position, true);
194             }
195         });
196     }
197 
198     private class BookListAdapter extends BaseAdapter {
199         private LayoutInflater layoutInflater;
200         private List<Book> bookList;
201         private boolean[] bookDetailExpanded;
202 
203         public BookListAdapter(Context context, List<Book> bookList) {
204             this.layoutInflater = LayoutInflater.from(context);
205             this.bookList = bookList;
206             this.bookDetailExpanded = new boolean[bookList.size()];
207         }
208 
209         @Override
210         public int getCount() {
211             return bookList.size();
212         }
213 
214         @Override
215         public Object getItem(int position) {
216             return bookList.get(position);
217         }
218 
219         @Override
220         public long getItemId(int position) {
221             return bookList.get(position).getId();
222         }
223 
224         @Override
225         public View getView(int position, View convertView, ViewGroup parent) {
226             if (convertView == null) {
227                 convertView = layoutInflater.inflate(
228                         R.layout.book_listview_item, parent, false);
229             }
230             TextView tvBookTitle = (TextView) convertView
231                     .findViewById(R.id.tvBookTitle);
232             TextView tvBookDetail = (TextView) convertView
233                     .findViewById(R.id.tvBookDetail);
234             Book book = bookList.get(position);
235 
236             tvBookTitle.setText(book.getName() + "  $" + book.getPrice());
237             tvBookDetail.setText("Author: " + book.getAuthor() + "  Type: "
238                     + book.getType());
239             tvBookDetail
240                     .setVisibility(bookDetailExpanded[position] ? View.VISIBLE
241                             : View.GONE);
242             return convertView;
243         }
244 
245         public void expand(int position) {
246             // 被點擊的資料列才會彈出內容,其他資料列的內容會自動縮起來
247             // for (int i=0; i<newsExpanded.length; i++) {
248             // newsExpanded[i] = false;
249             // }
250             // newsExpanded[position] = true;
251 
252             bookDetailExpanded[position] = !bookDetailExpanded[position];
253             notifyDataSetChanged();
254         }
255 
256     }
257 
258     @Override
259     protected void onPause() {
260         if (retrieveCategoryTask != null) {
261             retrieveCategoryTask.cancel(true);
262             retrieveCategoryTask = null;
263         }
264 
265         if (retrieveBookTask != null) {
266             retrieveBookTask.cancel(true);
267             retrieveBookTask = null;
268         }
269 
270         super.onPause();
271     }
272 
273     private void showToast(Context context, int messageId) {
274         Toast.makeText(context, messageId, Toast.LENGTH_SHORT).show();
275     }
276 }

 


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

-Advertisement-
Play Games
更多相關文章
  • 1. 首先先下載生成二維碼的支持文件 "libqrencode" 2. 添加依賴庫 CoreGraphics.framework 、 QuartzCore.framework 、 AVFoundation.framework 、 libiconv.dylib 、 CoreMedia.framewor ...
  • 對AFNetworking+MBProgressHUD的二次封裝,使用更方便,適用性非常強: 一句話搞定網路提示; 再也不用擔心網路庫更新後,工程要修改很多地方了!網路庫更新了只需要更新這個封裝好的庫。 不足之處歡迎指正 使用方法簡介: [MBProgressHUD showAutoMessage: ...
  • *res/raw和assets的相同點: 1.兩者目錄下的文件在打包後會原封不動的保存在apk包中,不會被編譯成二進位。 *res/raw和assets的不同點:1.res/raw中的文件會被映射到R.java文件中,訪問的時候直接使用資源ID即R.id.filename;assets文件夾下的文件 ...
  • 重寫onKeyDown事件即可 @Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { moveTaskToBack(false); return ...
  • 之前因為工作需要要實現一個類似的 懸浮+視差的headerView的效果, 研究了好久沒研究出來怎麼做,最後用UICollectionView + CSStickyHeaderFlowLayout的方法實現了(不得不說CSStickyHeaderFlowLayout真的是一個很強大的庫,作者對UIC ...
  • //顯示動畫 dialog = new Dialog(context, R.style.loading); dialog.setContentView(R.layout.loadinglayout);//此處佈局為一個progressbar dialog.setCancelable(true); / ...
  • 一,效果圖。 二,工程圖。 三,代碼。 AppDelegate.m #import "AppDelegate.h" //加入頭文件 #import "RoundDiskViewController.h" @implementation AppDelegate - (BOOL)application: ...
  • Android 5.0之後Android新增加的兩個UI控制項RecyclerView,CardView。 RecyclerView可以看出是ListView的加強版,能夠更加靈活的使用、支持動畫等 CardView則是Google提供的一個卡片式視圖組件,可以定義如邊角的弧度、陰影等屬性。從本質上看 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...