Android AsyncTask 异步任务

 【AsyncTask】


 1、前面已经介绍过,Android的UI线程主要负责处理用户的按键事件、用户触屏事件及屏幕绘图事件等,因此开发者的其他操作不应该、也不能阻塞UI线程,否则UI界面将会变得停止响应——用户感觉非常糟糕。我们可以开辟一个新的线程来解决这个问题,同时Android中为了简化我们的负担,引进了一个异步任务处理类AsyncTask类

2、 AsyncTask<>是一个抽象类,通常用于被继承,继承AsyncTask时需要指定如下三个泛型参数。

     相对来说AsyncTask更加轻量级一些,适用于简单的异步处理,不需要借助线程和Handler即可实现。

     AsyncTask<Params,Progress,Result>是抽象类,它定义了如下三种泛型类型。

  • Params:启动任务执行的输入参数的类型。
  • Progress:后台任务完成的进度值的类型。
  • Result:后台执行任务完成后返回结果的类型。

    使用AsyncTask只要如下三步即可。

  1.  使用AsyncTask的子类,并为三个泛型参数指定类型。如果某个泛型参数不需要指定类型,可将它指定为Void。
  2.  根据需要,实现AsyncTask的如下方法。
  • doInBackground(Params...):重写该方法就是后程序将要完成的任务。该方法可以调用publicProgress(Progress...values)方法更新任务的执行进度。
  • onProgressUpdate(Progress... values):在doInBackground()方法中调用publishProgress()方法更新任务的执行进度后,将会触发该方法。
  • onPreExecute():该方法将在执行后台耗时操作前被调用。通常该方法用于完成一些初始化的准备工作,比如在界面上显示进度条等。
  • onPostExecute(Result result):当doInBackground()完成后,系统会自动调用onPostExecute()方法,并将doInBackground()方法的返回值传给该方法。

     3.   调用AsyncTask子类的实例的execute(Params...params)开始执行耗时操作。使用AsyncTask时必须遵守如下规则。

  •   必须在UI线程中创建AsyncTask的实例。
  •   必须在UI线程中调用AsyncTask的execute()方法。
  •  AsyncTask的onPreExecute()、onPostExecute(Result result)、doInBackground(Params...params),onProgressUpdate(Progress... values)方法,不应该由程序员写代码调用,而是由Android系统负责调用。
  • 在同一个执行周期中,相同的AsyncTask实例只能被执行一次,多次调用将会引发异常。 

【实例】


我们还是以一个下载网页内容的应用来进行讲解,非常的简单,布局文件中仅有两个一个TextView和一个按钮,当我们点击按钮时,就开始为网页的读取,当读取完毕之后,就将内容显示在TextView中,我们知道在android 4.0之后,要求所有关于网络的代码必须全部放在新的线程中,否则就会崩掉,同样我们要将所有的关于网络的代码全部放在AsyncTask中,才能够正常运行

先来看看效果 :

异步任务类文件:

 1 package com.penglee.asynctask_test;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.IOException;
 5 import java.io.InputStreamReader;
 6 import java.net.URL;
 7 import java.net.URLConnection;
 8 import android.app.ProgressDialog;
 9 import android.content.Context;
10 import android.os.AsyncTask;
11 import android.widget.TextView;
12 
13 public class NetDownloadTask extends AsyncTask<URL , Integer , String>{
14     
15     Context context ;
16     ProgressDialog proDialog;
17     TextView textView ; //当前的主布局中的TextView
18     int hasRead=0; //当前已经读取的行数
19     
20     public NetDownloadTask(Context context , TextView view){
21         this.textView = view ;
22         this.context = context ;
23     }
24 
25     /**
26      *在任务执行之前会自动的调用这个方法,一般是做一些初始化
27      **/
28     @Override
29     protected void onPreExecute() {
30 
31         proDialog = new ProgressDialog(context);
32         //设置对话框的标题
33         proDialog.setTitle("正在进行页面下载");
34         //设置对话框显示的内容
35         proDialog.setMessage("网页下载中......");
36         //设置对话框不能用"取消"按钮关闭
37         proDialog.setCancelable(false);
38         //设置对话框的进度条风格
39         proDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
40         proDialog.show();
41         super.onPreExecute();
42 
43     }
44 
45     /**
46      * 真正的任务执行位置
47      * */
48     @Override
49     protected String doInBackground(URL... params) {
50         
51         StringBuilder stringContent = new StringBuilder() ;
52 
53         try {
54             URLConnection conn=params[0].openConnection();
55             BufferedReader bReader = new BufferedReader(new InputStreamReader(conn.getInputStream(),"utf-8"));
56             String tempString = null ;
57             while((tempString= bReader.readLine())!=null){
58                 stringContent.append(tempString + "\n");
59                 hasRead++ ;
60                 publishProgress(hasRead);//调用这个方法的时候会自动的调用onProgressUpdate方法
61             }
62         } catch (IOException e) {
63             e.printStackTrace();
64         }
65         
66         return stringContent.toString();
67     }
68 
69     /**
70      * 在这个方法中更新进度,或者说,在这个方法中可以更改UI界面
71      * */
72     @Override
73     protected void onProgressUpdate(Integer... values) {
74         textView.setText("当前已经读取了"+values[0]+"行数据");        
75         super.onProgressUpdate(values);
76     }
77 
78     /**
79      * 当doInBackground方法执行完毕之后,就会自动的回到这个方法
80      * */
81     @Override
82     protected void onPostExecute(String result) {
83         textView.setText(result);
84         //proDialog.dismiss(); //将进度条对话框销毁
85         super.onPostExecute(result);
86     }
87     
88 }


主布局文件:

 1 <RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
 6     android:paddingLeft="@dimen/activity_horizontal_margin"
 7     android:paddingRight="@dimen/activity_horizontal_margin"
 8     android:paddingTop="@dimen/activity_vertical_margin"
 9     tools:context="com.penglee.asynctask_test.MainActivity" >
10 
11     <TextView
12         android:id="@+id/textView"
13         android:layout_width="match_parent"
14         android:layout_height="match_parent"/>
15     
16     <Button 
17         android:layout_width="match_parent"
18         android:layout_height="wrap_content"
19         android:layout_alignParentBottom="true"
20         android:text="开始下载天猫网页"
21         android:onClick="onClick"/>
22 
23 </RelativeLayout>


主Activity文件

 1 package com.penglee.asynctask_test;
 2 
 3 import java.net.MalformedURLException;
 4 import java.net.URL;
 5 
 6 import android.app.Activity;
 7 import android.os.Bundle;
 8 import android.view.Menu;
 9 import android.view.MenuItem;
10 import android.view.View;
11 import android.widget.TextView;
12 
13 public class MainActivity extends Activity {
14     
15     TextView textView ;
16 
17     @Override
18     protected void onCreate(Bundle savedInstanceState) {
19         super.onCreate(savedInstanceState);
20         setContentView(R.layout.activity_main);
21         
22         textView = (TextView)findViewById(R.id.textView);
23     }
24     
25     public void onClick(View view) throws MalformedURLException{
26         new NetDownloadTask(MainActivity.this ,textView )
27                                       .execute(new URL("http://www.tianmao.com/"));
28     }
29     
30 
31     @Override
32     public boolean onCreateOptionsMenu(Menu menu) {
33         // Inflate the menu; this adds items to the action bar if it is present.
34         getMenuInflater().inflate(R.menu.main, menu);
35         return true;
36     }
37 
38     @Override
39     public boolean onOptionsItemSelected(MenuItem item) {
40         // Handle action bar item clicks here. The action bar will
41         // automatically handle clicks on the Home/Up button, so long
42         // as you specify a parent activity in AndroidManifest.xml.
43         int id = item.getItemId();
44         if (id == R.id.action_settings) {
45             return true;
46         }
47         return super.onOptionsItemSelected(item);
48     }
49 }

最后注意在Manifest.xml文件中添加网络访问权限,一般将数据网络和WiFi网络权限都添加上

posted @ 2014-12-04 20:35  RoperLee  阅读(199)  评论(0)    收藏  举报