Android AsyncTask 详解及注意事项_移动开发_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > 移动开发 > Android AsyncTask 详解及注意事项

Android AsyncTask 详解及注意事项

 2016/7/7 5:31:18  Linccy  程序员俱乐部  我要评论(0)
  • 摘要:AsyncTask是Android提供的轻量级的异步类,它使创建异步任务变得更加简单,不再需要编写任务线程和Handler实例即可完成相同的任务。AsyncTask定义了三种泛型类型Params,Progress和Result。Params启动任务执行的输入参数,比如HTTP请求的URL。Progress后台任务执行的百分比。Result后台执行任务最终返回的结果,比如String。例如:classRetrieveCategoryTaskextendsAsyncTask<String
  • 标签:android 详解 注意事项 事项
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 }

 

发表评论
用户名: 匿名