zoukankan      html  css  js  c++  java
  • Android AsyncTask 详解及注意事项

    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 }
  • 相关阅读:
    Bootstrap4(28): 滚动监听(Scrollspy)
    Bootstrap4(27): 弹出框
    Bootstrap4(26): 提示框
    Bootstrap4(25): 模态框
    Bootstrap4(24): 轮播
    Bootstrap4(23): 自定义表单
    Bootstrap4(22): 输入框组
    Bootstrap4(21): 表单控件
    Bootstrap4(20): 表单
    Bootstrap4(19): 面包屑导航(Breadcrumb)
  • 原文地址:https://www.cnblogs.com/Linccy/p/5648540.html
Copyright © 2011-2022 走看看