Android中关于AsyncTask异步任务的使用

 

昨天面试的时候在异步任务(AsyncTask)下载文件时出现了一点问题,今天把它好好整理了一下,有兴趣的人可以看一下。
关于Android的异步机制有两种方式,Handler和AsyncTask。他们各自有自己的优点和缺点,AsyncTask:直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程序在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来。Handler:对于多个后台任务时,简单,清晰,在单个后台异步处理时,显得代码过多,结构相对来说较复杂。关于Handler不再说,下面我们来仔细研究一下AsyncTask。

AsyncTask定义了三种泛型类型 Params,Progress和Result。
Params 启动任务执行的输入参数,比如HTTP请求的URL。
Progress 后台任务执行的百分比。
Result 后台执行任务最终返回的结果,比如String。

一个异步任务的执行一般包括以下几个步骤:
1.excute(Params....params)执行一个异步任务,需要我们在UI线程中调用此方法,触发异步任务的执行。
2.onPreExcute()该方法在执行后台耗时性操作之前被调用,用于完成初始化准备工作。
3.dioInbackground()在onPreExcute()方法完成后立即执行,用于执行较为费时的后台操作,此方法将接收输入参数和返回计算结果。在执行过程中可以调用来publishProgress(Progress...values)更新进度信息。onPostExecute(Result result)
4.onProgressUpdate(Progress...values)在调用publishProgress(Progress... values)时,此方法被执行,直接将进度信息更新到UI组件上。
5.onPostExecute(Result result)当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法中,直接将结果显示到UI组件上。

使用AsyncTask类,我们需要注意的是:
Task的实例必须在UI thread中创建;
execute方法必须在UI thread中调用;
不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法;
该task只能被执行一次,否则多次调用时将会出现异常;
下面看一个简单的 AsyncTask 例子:

  1 public class AsyncTaskDemo extends Activity {
  2 
  3     private TextView show;
  4 
  5     @Override
  6     protected void onCreate(Bundle savedInstanceState) {
  7         super.onCreate(savedInstanceState);
  8         setContentView(R.layout.activity_main);
  9         show = (TextView) findViewById(R.id.show);
 10     }
 11 
 12     // 为界面按钮提供响应的方法
 13     public void download(View source) throws MalformedURLException {
 14         // UI线程中创建AsyncTask的实例
 15         DownTask task = new DownTask(this);
 16         // UI线程中调用execute()方法,这里的URL设置的是打开图片,如果大家想打开网页,会出现无法获得
 17         //总长度,因此无法更新进度条的进度,只能用模拟进度
 18         task.execute(new URL("http://www.baidu.com/img/bdlogo.gif"));
 19     }
 20 
 21     class DownTask extends AsyncTask<URL, Integer, String> {
 22 
 23         // 定义一个Dialog用于显示下载任务
 24         ProgressDialog pDialog;
 25         // 定义记录读取的行数
 26         int hasRead = 0;
 27         Context mContext;
 28         private int totalCount;
 29 
 30         public DownTask(Context ctx) {
 31             mContext = ctx;
 32         }
 33 
 34         @Override
 35         // 后台线程将要完成的任务
 36         protected String doInBackground(URL... params) {
 37             Log.d("TAG", "doInBackground 1");
 38             StringBuffer sb = new StringBuffer();
 39             try {
 40                 URLConnection conn = params[0].openConnection();
 41                 conn.connect();
 42                 totalCount =  conn.getContentLength();
 43                 Log.d("TAG", "doInBackground totalCount:" + totalCount);
 44                 // 打开连接对应的输入流,并将他包装成BufferReader
 45                 BufferedReader bf = new BufferedReader(new InputStreamReader(
 46                         conn.getInputStream(), "utf-8"));
 47                 String line = null;
 48                 while ((line = bf.readLine()) != null) {
 49                     sb.append(line + "\n");
 50                     hasRead++;
 51                     // 用于更新任务的执行
 52                     Log.d("TAG", "doInBackground sb.length():" + sb.length());
 53                     publishProgress(sb.length());
 54                 }
 55             } catch (IOException e) {
 56                 e.printStackTrace();
 57             }
 58             return sb.toString();
 59         }
 60 
 61         @Override
 62         // 在doInBackground()方法执行完后自动执行
 63         protected void onPostExecute(String result) {
 64             Log.d("TAG", "onPostExecute 1");
 65             // 返回html页面的内容
 66             show.setText(result);
 67             // 移除对话框
 68             pDialog.dismiss();
 69         }
 70 
 71         @Override
 72         // 在执行后台才做之前调用完成一些初始化的准备
 73         protected void onPreExecute() {
 74             Log.d("TAG", "onPreExecute 1");
 75 
 76             pDialog = new ProgressDialog(mContext);
 77             // 设置对话框的标题
 78             pDialog.setTitle("任务正在执行中");
 79             // 设置对话框的显示内容
 80             pDialog.setMessage("任务正在执行中,请等待");
 81             // 设置对话框不能用“取消”进行关闭
 82             pDialog.setCancelable(false);
 83             // 设置对话框的最大显示进度
 84             pDialog.setMax(100);
 85             // 设置对话框的显示风格
 86             pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
 87             // 设置对话框的进度条是否显示进度
 88             pDialog.setIndeterminate(false);
 89             // 显示对话框
 90             pDialog.show();
 91 
 92         }
 93 
 94         @Override
 95         // 在doInBackground()调用publishProgress()方法后,触发该方法
 96         protected void onProgressUpdate(Integer... values) {
 97             Log.d("TAG", "onProgressUpdate 2");
 98 
 99             // 更新进度
100             show.setText("你已经读取了【" + values[0] + "】行!");
101             pDialog.setProgress((int)(values[0] / (float)totalCount * 100));
102 
103         }
104 
105     }
106 
107 }

 xml中的代码:

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2       xmlns:tools="http://schemas.android.com/tools"
 3       android:layout_width="match_parent"
 4       android:layout_height="match_parent"
 5       android:orientation="vertical"
 6       tools:context=".AsyncTaskDemo" >
 7   
 8     <Button
 9         android:id="@+id/download"
10         android:layout_width="match_parent"
11         android:layout_height="wrap_content"
12         android:onClick="download"
13         android:text="开始下载" />
14  
15     <TextView
16          android:id="@+id/show"
17          android:layout_width="match_parent"
18          android:layout_height="wrap_content"
19          android:text="获取资源" />
20   </LinearLayout>

  下面是运行结果:

 

转载于:https://www.cnblogs.com/hule/p/3458017.html

猜你喜欢

转载自blog.csdn.net/weixin_34227447/article/details/93982851
今日推荐