第82章、异步处理工具类:AsyncTask(从零开始学Android)

(一)  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文件。
  输入以下代码:

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <EditText
        android:id="@+id/url"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true" >
        <requestFocus />
    </EditText>

    <Button
        android:id="@+id/open"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:text="AsyncTask处理" />

    <EditText
        android:id="@+id/message"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textMultiLine" />

</LinearLayout>


二、程序文件

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

package com.genwoxue.asynctask;

import java.io.ByteArrayOutputStream;  
import java.io.InputStream;  
import org.apache.http.HttpEntity;  
import org.apache.http.HttpResponse;  
import org.apache.http.client.HttpClient;  
import org.apache.http.client.methods.HttpGet;  
import org.apache.http.impl.client.DefaultHttpClient;   
import android.app.Activity;  
import android.app.ProgressDialog;  
import android.content.Context;  
import android.content.DialogInterface;  
import android.os.AsyncTask;  
import android.os.Bundle;  
import android.view.View;  
import android.widget.Button;  
import android.widget.EditText;  
import android.widget.TextView;   

public class MainActivity extends Activity{   
	private EditText message;      
	private Button open;      
	private EditText url;      
	
	@Override     
	public void onCreate(Bundle savedInstanceState) {         
		super.onCreate(savedInstanceState);         
		setContentView(R.layout.activity_main);         
		message= (EditText) findViewById(R.id.message);         
		url= (EditText) findViewById(R.id.url);       
		url.setText("http://www.genwoxue.com");
		open= (Button) findViewById(R.id.open);         
		open.setOnClickListener(new View.OnClickListener() {             
			public void onClick(View arg0) {              
				connect();         
				}       
			});       
		}     
	private void connect() {   
		PageTask task = new PageTask(this);      
		task.execute(url.getText().toString());    
	}      
	
	/* 四个步骤:
	 * (1)onPreExecute(),执行预处理,它运行于UI线程,
	 * 可以为后台任务做一些准备工作,比如绘制一个进度条控件。
	 * (2)doInBackground(Params...),后台进程执行的具体计算在这里实现,
	 * doInBackground(Params...)是AsyncTask的关键,此方法必须重载。
	 * 在这个方法内可以使用 publishProgress(Progress...)改变当前的进度值。
	 * (3)onProgressUpdate(Progress...),运行于UI线程。如果
	 * 在doInBackground(Params...) 中使用了publishProgress(Progress...),就会
	 * 触发这个方法。在这里可以对进度条控件根据进度值做出具体的响应。
	 * (4)onPostExecute(Result),运行于UI线程,可以对后台任务的结果做出处理,结果
	 * 就是doInBackground(Params...)的返回值。此方法也要经常重载,如果Result为
	 * null表明后台任务没有完成(被取消或者出现异常)。	 * 
	 */
	class PageTask extends AsyncTask<String, Integer, String> {    
		// 可变长的输入参数,与AsyncTask.exucute()对应    
		ProgressDialog pdialog;    
		public PageTask(Context context){    
			pdialog = new ProgressDialog(context, 0);   
			pdialog.setButton("cancel", new DialogInterface.OnClickListener() { 
				public void onClick(DialogInterface dialog, int i) {    
					dialog.cancel();        
				}          
			});          
			
		pdialog.setOnCancelListener(new DialogInterface.OnCancelListener() {     
				public void onCancel(DialogInterface dialog) {           
					finish();           
				}          
		});          
		
		pdialog.setCancelable(true);   
		pdialog.setMax(100);         
		pdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);     
		pdialog.show();           
	}    
		
		// (1)任务启动
		@Override        
		protected void onPreExecute() {     
			message.setText("task_started");        
		}  
		
		//(2)后台执行:主要工作在这里实现
		@Override          
		protected String doInBackground(String... params) {   
			String result = null;
			try{               
				HttpClient client = new DefaultHttpClient();       
				HttpGet get = new HttpGet(params[0]);       // params[0]代表连接的url      
				HttpResponse response = client.execute(get);        
				HttpEntity entity = response.getEntity();            
				long length = entity.getContentLength();              
				InputStream is = entity.getContent();                
				if(is != null) {                     
					ByteArrayOutputStream baos = new ByteArrayOutputStream();          
					byte[] buf = new byte[128];                  
					int ch = -1;                   
					int count = 0;                  
					while((ch = is.read(buf)) != -1) {        
						baos.write(buf, 0, ch);   
						
						count += ch;                        
						if(length > 0) {                           
							// 如果知道响应的长度,调用publishProgress()更新进度          
							publishProgress((int) ((count / (float) length) * 100));                
							}                         
							Thread.sleep(50);    // 让线程休眠50ms                
						}          
					result = new String(baos.toByteArray());          
				}              
					return result;     // 返回结果            
			} catch(Exception e) {         
				e.printStackTrace();        
			}             
			return null;      
		}          
		
		
		//(3)由doInBackground中的publishProgress(Progress...)触发onProgressUpdate这个方法
		@Override       
		protected void onProgressUpdate(Integer... values) {      
			// 更新进度            
			System.out.println(""+values[0]);   
			message.setText(""+values[0]);    
			pdialog.setProgress(values[0]);      
		}      
				
		//(4)可以对后台任务的结果做出处理,结果就是doInBackground(Params...)的返回值。
		@Override     
		protected void onPostExecute(String result) {    
			// 返回HTML页面的内容              
			message.setText(result);       
			pdialog.dismiss();         
		}  
		
		@Override          
		protected void onCancelled() {     
			super.onCancelled();        
		}    
		
	}   
}


三、配置文件

  打开“AndroidManifest.xml”文件。

  然后输入以下代码:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.genwoxue.asynctask"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="15" />
    
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.genwoxue.asynctask.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


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

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

四、运行结果

    
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蒋会全

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值