频道栏目
首页 > 程序开发 > 移动开发 > Android教程 > Android基础教程 > 正文
第82章、异步处理工具类:AsyncTask(从零开始学Android)
2016-02-02 17:13:27      个评论      
收藏   我要投稿
(一)  AsyncTask,是android提供的轻量级的异步类。可以直接继承AsyncTask,在类中实现异步操作,可以通过接口实现UI进度更新,最后反馈执行的结果给UI主线程

。之所以有Handler和AsyncTask,都是为了不阻塞主线程(UI线程),且UI的更新只能在主线程中完成,因此异步处理是不可避免的。

AsyncTask直接继承于Object类,位置为android.os.AsyncTask。要使用AsyncTask工作我们要提供三个泛型参数,并重载几个方法(至少重载一个)。

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

2、使用过AsyncTask 最少要重写以下这两个方法:
(1)doInBackground(Params…) 后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。

(2)onPostExecute(Result) 相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回

另外三个方法可选,不是必须的:

(3)onProgressUpdate(Progress…) 可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。
(4)onPreExecute() 这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。
(5)onCancelled() 用户调用取消时,要做的操作

3、使用AsyncTask类,以下是几条必须遵守的准则:
(1)Task的实例必须在UI thread中创建;
(2)execute方法必须在UI thread中调用;
(3)不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法;
(4)该task只能被执行一次,否则多次调用时将会出现异常;

(二)AsyncTask和Handler对比

1、AsyncTask实现的原理,和适用的优缺点

AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程.

(1)使用的优点:

A、简单,快捷;
B、过程可控。

(2)使用的缺点:

在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来。

2、Handler异步实现的原理和适用的优缺点

在Handler 异步实现时,涉及到Handler、Looper、Message、Thread四个对象,实现异步的流程是主线程启动Thread(子线程)àthread(子线程)运行并生成Message-Looper获取Message并传递给HandleràHandler逐个获取Looper中的Message,并进行UI变更。

(1)使用的优点:

A、 结构清晰,功能定义明确

B、 对于多个后台任务时,简单,清晰

 

(2)使用的缺点:

在单个后台异步处理时,显得代码过多,结构过于复杂(相对性)

 

一、设计界面

1、布局文件

打开res/layout/activity_main.xml文件。
输入以下代码:

[html] view plain copy

 

  1. <LinearLayout   
  2.     xmlns:android="https://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="vertical" >  
  6.     <EditText  
  7.         android:id="@+id/url"  
  8.         android:layout_width="wrap_content"  
  9.         android:layout_height="wrap_content"  
  10.         android:layout_alignParentLeft="true" >  
  11.         <requestFocus />  
  12.     </EditText>  
  13.   
  14.     <Button  
  15.         android:id="@+id/open"  
  16.         android:layout_width="wrap_content"  
  17.         android:layout_height="wrap_content"  
  18.         android:layout_alignParentLeft="true"  
  19.         android:text="AsyncTask处理" />  
  20.   
  21.     <EditText  
  22.         android:id="@+id/message"  
  23.         android:layout_width="match_parent"  
  24.         android:layout_height="wrap_content"  
  25.         android:inputType="textMultiLine" />  
  26.   
  27. </LinearLayout>  

 

二、程序文件

打开“src/com.genwoxue.contentprovider_b/MainActivity.java”文件。
然后输入以下代码:

[java] view plain copy

 

  1. package com.genwoxue.asynctask;  
  2.   
  3. import java.io.ByteArrayOutputStream;    
  4. import java.io.InputStream;    
  5. import org.apache.http.HttpEntity;    
  6. import org.apache.http.HttpResponse;    
  7. import org.apache.http.client.HttpClient;    
  8. import org.apache.http.client.methods.HttpGet;    
  9. import org.apache.http.impl.client.DefaultHttpClient;     
  10. import android.app.Activity;    
  11. import android.app.ProgressDialog;    
  12. import android.content.Context;    
  13. import android.content.DialogInterface;    
  14. import android.os.AsyncTask;    
  15. import android.os.Bundle;    
  16. import android.view.View;    
  17. import android.widget.Button;    
  18. import android.widget.EditText;    
  19. import android.widget.TextView;     
  20.   
  21. public class MainActivity extends Activity{     
  22.     private EditText message;        
  23.     private Button open;        
  24.     private EditText url;        
  25.       
  26.     @Override       
  27.     public void onCreate(Bundle savedInstanceState) {           
  28.         super.onCreate(savedInstanceState);           
  29.         setContentView(R.layout.activity_main);           
  30.         message= (EditText) findViewById(R.id.message);           
  31.         url= (EditText) findViewById(R.id.url);         
  32.         url.setText("https://www.genwoxue.com");  
  33.         open= (Button) findViewById(R.id.open);           
  34.         open.setOnClickListener(new View.OnClickListener() {               
  35.             public void onClick(View arg0) {                
  36.                 connect();           
  37.                 }         
  38.             });         
  39.         }       
  40.     private void connect() {     
  41.         PageTask task = new PageTask(this);        
  42.         task.execute(url.getText().toString());      
  43.     }        
  44.       
  45.     /* 四个步骤: 
  46.      * (1)onPreExecute(),执行预处理,它运行于UI线程, 
  47.      * 可以为后台任务做一些准备工作,比如绘制一个进度条控件。 
  48.      * (2)doInBackground(Params...),后台进程执行的具体计算在这里实现, 
  49.      * doInBackground(Params...)是AsyncTask的关键,此方法必须重载。 
  50.      * 在这个方法内可以使用 publishProgress(Progress...)改变当前的进度值。 
  51.      * (3)onProgressUpdate(Progress...),运行于UI线程。如果 
  52.      * 在doInBackground(Params...) 中使用了publishProgress(Progress...),就会 
  53.      * 触发这个方法。在这里可以对进度条控件根据进度值做出具体的响应。 
  54.      * (4)onPostExecute(Result),运行于UI线程,可以对后台任务的结果做出处理,结果 
  55.      * 就是doInBackground(Params...)的返回值。此方法也要经常重载,如果Result为 
  56.      * null表明后台任务没有完成(被取消或者出现异常)。    *  
  57.      */  
  58.     class PageTask extends AsyncTask<String, Integer, String> {      
  59.         // 可变长的输入参数,与AsyncTask.exucute()对应      
  60.         ProgressDialog pdialog;      
  61.         public PageTask(Context context){      
  62.             pdialog = new ProgressDialog(context, 0);     
  63.             pdialog.setButton("cancel", new DialogInterface.OnClickListener() {   
  64.                 public void onClick(DialogInterface dialog, int i) {      
  65.                     dialog.cancel();          
  66.                 }            
  67.             });            
  68.               
  69.         pdialog.setOnCancelListener(new DialogInterface.OnCancelListener() {       
  70.                 public void onCancel(DialogInterface dialog) {             
  71.                     finish();             
  72.                 }            
  73.         });            
  74.           
  75.         pdialog.setCancelable(true);     
  76.         pdialog.setMax(100);           
  77.         pdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);       
  78.         pdialog.show();             
  79.     }      
  80.           
  81.         // (1)任务启动  
  82.         @Override          
  83.         protected void onPreExecute() {       
  84.             message.setText("task_started");          
  85.         }    
  86.           
  87.         //(2)后台执行:主要工作在这里实现  
  88.         @Override            
  89.         protected String doInBackground(String... params) {     
  90.             String result = null;  
  91.             try{                 
  92.                 HttpClient client = new DefaultHttpClient();         
  93.                 HttpGet get = new HttpGet(params[0]);       // params[0]代表连接的url        
  94.                 HttpResponse response = client.execute(get);          
  95.                 HttpEntity entity = response.getEntity();              
  96.                 long length = entity.getContentLength();                
  97.                 InputStream is = entity.getContent();                  
  98.                 if(is != null) {                       
  99.                     ByteArrayOutputStream baos = new ByteArrayOutputStream();            
  100.                     byte[] buf = new byte[128];                    
  101.                     int ch = -1;                     
  102.                     int count = 0;                    
  103.                     while((ch = is.read(buf)) != -1) {          
  104.                         baos.write(buf, 0, ch);     
  105.                           
  106.                         count += ch;                          
  107.                         if(length > 0) {                             
  108.                             // 如果知道响应的长度,调用publishProgress()更新进度            
  109.                             publishProgress((int) ((count / (float) length) * 100));                  
  110.                             }                           
  111.                             Thread.sleep(50);    // 让线程休眠50ms                  
  112.                         }            
  113.                     result = new String(baos.toByteArray());            
  114.                 }                
  115.                     return result;     // 返回结果              
  116.             } catch(Exception e) {           
  117.                 e.printStackTrace();          
  118.             }               
  119.             return null;        
  120.         }            
  121.           
  122.           
  123.         //(3)由doInBackground中的publishProgress(Progress...)触发onProgressUpdate这个方法  
  124.         @Override         
  125.         protected void onProgressUpdate(Integer... values) {        
  126.             // 更新进度              
  127.             System.out.println(""+values[0]);     
  128.             message.setText(""+values[0]);      
  129.             pdialog.setProgress(values[0]);        
  130.         }        
  131.                   
  132.         //(4)可以对后台任务的结果做出处理,结果就是doInBackground(Params...)的返回值。  
  133.         @Override       
  134.         protected void onPostExecute(String result) {      
  135.             // 返回HTML页面的内容                
  136.             message.setText(result);         
  137.             pdialog.dismiss();           
  138.         }    
  139.           
  140.         @Override            
  141.         protected void onCancelled() {       
  142.             super.onCancelled();          
  143.         }      
  144.           
  145.     }     
  146. }  

 

三、配置文件

打开“AndroidManifest.xml”文件。

然后输入以下代码:

[html] view plain copy

 

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="https://schemas.android.com/apk/res/android"  
  3.     package="com.genwoxue.asynctask"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.   
  7.     <uses-sdk  
  8.         android:minSdkVersion="10"  
  9.         android:targetSdkVersion="15" />  
  10.       
  11.     <span style="color:#ff0000;"><strong><uses-permission android:name="android.permission.INTERNET"/></strong>  
  12. </span>  
  13.     <application  
  14.         android:allowBackup="true"  
  15.         android:icon="@drawable/ic_launcher"  
  16.         android:label="@string/app_name"  
  17.         android:theme="@style/AppTheme" >  
  18.         <activity  
  19.             android:name="com.genwoxue.asynctask.MainActivity"  
  20.             android:label="@string/app_name" >  
  21.             <intent-filter>  
  22.                 <action android:name="android.intent.action.MAIN" />  
  23.   
  24.                 <category android:name="android.intent.category.LAUNCHER" />  
  25.             </intent-filter>  
  26.         </activity>  
  27.     </application>  
  28.   
  29. </manifest>  

 

注意:需要在AndroidManifest.xml文件中添加权限:

<uses-permission android:name="android.permission.INTERNET"/>

四、运行结果

\ \
点击复制链接 与好友分享!回本站首页
相关TAG标签 工具
上一篇:第102章、百度地图初探(从零开始学Android)
下一篇:第100章、WebView应用之Javascript调用Android(从零开始学Android)
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站