Asynctask是Android中封装好了一个执行异步操作的抽象类。在执行一些耗时操作时可以借助该类来实现。相当于线程和Handler消息机制的一种封装。
一、Asybctask的基本用法。
Asybctask是一个抽象类,要使用它,可以定义一个子类继承它,在继承中会出现三个参数。
1、Params 该参数是执行AsyncTask时需要传入的参数类型,可以用于后台任务中使用,若不需要传入参数,那么就设置为Viod(注意V是大写的)。
2、Progress 该参数是后台任务执行时,若果需要在界面上显示当前的进度,则使用这里指定的泛型类型作为进度单位。
3、Resuit 任务执行完毕,需要返回的结果的类型。
若不需要三个泛型参数的任意一个,都应给用Void代替。
下面就来实现一个加载进度条的操作Demo:
异步任务实现加载进度条、
public class MyAsynctask extends AsyncTask<Void, Integer, String>{
@Override
/*最先执行的回调函数*/
protected void onPreExecute() {
super.onPreExecute();
Mylog.d("--------onPreExecute-------");
}
@Override
/*执行异步任务的回调方法 子线程中执行*/
protected String doInBackground(Void... params) { //Void... params 动态数组 子线程中执行
Mylog.d("--------doInBackground-------");
for(int i = 1;i <= 100; i++){
publishProgress(i);//异步操作中的参数传递方法。调用一次就会执行一次onProgressUpdate()回调函数
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String result = "下载完成";
return result;
}
@Override
/*执行异步任务中时要调用的回调函数 UI线程中执行
* 当 doInBackground方法中调用了publishProgress()方法时才会执行onProgressUpdate()方法*/
protected void onProgressUpdate(Integer... values) { //UI线程中执行,更新空间操作
super.onProgressUpdate(values);
Mylog.d("--------onProgressUpdate-------");
int progress = values[0]; //参数是动态数组,所以要先接收
mSeekBar.setProgress(progress);
mProgressTxt.setText(""+progress);
}
@Override
/*异步操作结束时调用的回调函数 UI线程中执行
* */
protected void onPostExecute(String result) { // 最后的结果
super.onPostExecute(result);
Mylog.d("--------onPostExecute-------");
mProgressTxt.setText(result);
}
}
这里面有几个方法,onPreExecute()是在执行了构造方法后调用的方法。接下来是doInBackground(),这个方法时在子线程中进行的,不能执行控件更新操作,这里面执行后台耗时操作。里面有一个动态数组的参数,也就是构造AsyncTask时需要传入的参数,类型为Void。
接下来是onProgressUpdate()方法,该方法是在异步任务执行中,若doInBackground()中调用了publishProgress()传递参数过来,那么传递一次,onProgressUpdate()就执行一次。这些的前提都要是在构造AsyncTask指定了Progress参数类型部位空的情况下。简单的说这个Progress类型就是异步任务执行中传递参数的类型,也就是在doInBackground()方法里通过publishProgress(参数)传递给onProgressUpdate()方法。由于onProgressUpdate()是在UI主线程中执行,所以可以在里面执行更新ui控件的操作。
最后是onPostExecute()这个方法,这个方法是异步任务执行完成后返回的数据。前提也要是在构造AsyncTask时设置了第三个参数Rusilt类型。这个方法就可以得到doInBackground()返回的结果。
构造好子类后就是怎么运用AsyncTask子类了。AsyncTask子类对象直接调用execute()方法。就可以开启该异步任务了。execute()里对应的参数就是构造AsyncTask子类时设定的参数类型。
<span style="white-space:pre"> </span>MyAsynctask myAsynctask = new MyAsynctask();
myAsynctask.execute(); //开始加载
下面是用线程加Handler实现加载进度条的Demo:
/*handler更新控件*/
public void startByThread(){
new Thread(new Runnable() {
@Override
public void run() {
for(int i = 1;i <= 100;i++){
mSeekBar.setProgress(i);
Message msg = Message.obtain();
msg.obj = i;
msg.what = 1;
mHandler.sendMessage(msg); //发送一个消息就应该Message.obtain()一个消息。也就是这两个方法配套出现。
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Message msg = Message.obtain();
msg.what = 2;
msg.obj = "加载完成";
mHandler.sendMessage(msg);
}
}).start();
}
最后贴上运行效果。
这里还有异步操作实现了从网络中下载图片的Demo:
从网络获取图片的方法:访问网络资源需要在AndroidManifest文件中设置权限
<uses-permission android:name="android.permission.INTERNET"/>
/*连接网络取数据*/
public Bitmap getPicture(String URLpath){
try {
URL url = new URL(URLpath);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
InputStream in = conn.getInputStream(); //将对应地址的图片读入流
Bitmap bitmap = BitmapFactory.decodeStream(in); //将流转化为Bitmap对象。
return bitmap;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
按钮事件用的匿名内部类实现。
<span style="white-space:pre"> </span>String urlPath = "http://img4.imgtn.bdimg.com/it/u=52754568,3369504778&fm=23&gp=0.jpg";
new AsyncTask<String, Void, Bitmap>(){
@Override
protected Bitmap doInBackground(String... params) {
return getPicture(params[0]); //下载图片
}
@Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
mImg.setImageBitmap(result);
}
}.execute(urlPath);
实现效果就是上面展示的效果。最后贴上所有Demo。
activity:
package asynctask;
/**
* 异步任务。线程和Handler的封装
*/
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import mylog.Mylog;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import com.example.call.R;
public class AsynctaskActivity extends Activity implements OnClickListener{
private TextView mProgressTxt;
private SeekBar mSeekBar;
private Button mThreadStartBtn,mAsyncTaskStartBtn,mDownloadPrictureBtn;
private ImageView mImg;
private Handler mHandler = new Handler(){
public void handleMessage(android.os.Message msg) {
switch(msg.what){
case 1:
mProgressTxt.setText(""+msg.obj);
break;
case 2:
mProgressTxt.setText(""+msg.obj);
}
};};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.asynctask_main_layout);
initView();
}
public void initView(){
mProgressTxt = (TextView) findViewById(R.id.show_progress_txt);
mSeekBar = (SeekBar) findViewById(R.id.asynctask_seekbar);
mThreadStartBtn = (Button) findViewById(R.id.thread_start_btn);
mImg = (ImageView) findViewById(R.id.downloadpicture_img);
mThreadStartBtn.setOnClickListener(this);
mAsyncTaskStartBtn = (Button) findViewById(R.id.asybctask_start_btn);
mAsyncTaskStartBtn.setOnClickListener(this);
mDownloadPrictureBtn = (Button) findViewById(R.id.asybctask_downloadPicture_btn);
mDownloadPrictureBtn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch(v.getId()){
case R.id.thread_start_btn:
startByThread();
break;
case R.id.asybctask_start_btn:
MyAsynctask myAsynctask = new MyAsynctask();
myAsynctask.execute(); //开始加载
break;
case R.id.asybctask_downloadPicture_btn:
String urlPath = "http://img4.imgtn.bdimg.com/it/u=52754568,3369504778&fm=23&gp=0.jpg";
new AsyncTask<String, Void, Bitmap>(){
@Override
protected Bitmap doInBackground(String... params) {
return getPicture(params[0]); //下载图片
}
@Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
mImg.setImageBitmap(result);
}
}.execute(urlPath);
break;
}
}
/*连接网络取数据*/
public Bitmap getPicture(String URLpath){
try {
URL url = new URL(URLpath);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
InputStream in = conn.getInputStream(); //将对应地址的图片读入流
Bitmap bitmap = BitmapFactory.decodeStream(in); //将流转化为Bitmap对象。
return bitmap;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/*handler更新控件*/
public void startByThread(){
new Thread(new Runnable() {
@Override
public void run() {
for(int i = 1;i <= 100;i++){
mSeekBar.setProgress(i);
Message msg = Message.obtain();
msg.obj = i;
msg.what = 1;
mHandler.sendMessage(msg); //发送一个消息就应该Message.obtain()一个消息。也就是这两个方法配套出现。
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Message msg = Message.obtain();
msg.what = 2;
msg.obj = "加载完成";
mHandler.sendMessage(msg);
}
}).start();
}
/*Asybctack启动加载方式
* AsyncTask<Void, Integer, String>
* 第一个参数 params为调用execute()传进来的参数类型 Void表示无参数
* 第二个参数Progress为在异步操作执行中传递的参数类型。在doInBackground()中调用publishProgress()就可以将参数传递给onProgressUpdate()方法,从而更新UI控件
* 第三个参数 result是异步操作执行完成返回的参数类型
* */
public class MyAsynctask extends AsyncTask<Void, Integer, String>{
@Override
/*最先执行的回调函数*/
protected void onPreExecute() {
super.onPreExecute();
Mylog.d("--------onPreExecute-------");
}
@Override
/*执行异步任务的回调方法 子线程中执行*/
protected String doInBackground(Void... params) { //Void... params 动态数组 子线程中执行
Mylog.d("--------doInBackground-------");
for(int i = 1;i <= 100; i++){
publishProgress(i);//异步操作中的参数传递方法。调用一次就会执行一次onProgressUpdate()回调函数
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String result = "下载完成";
return result;
}
@Override
/*执行异步任务中时要调用的回调函数 UI线程中执行
* 当 doInBackground方法中调用了publishProgress()方法时才会执行onProgressUpdate()方法*/
protected void onProgressUpdate(Integer... values) { //UI线程中执行,更新空间操作
super.onProgressUpdate(values);
Mylog.d("--------onProgressUpdate-------");
int progress = values[0]; //参数是动态数组,所以要先接收
mSeekBar.setProgress(progress);
mProgressTxt.setText(""+progress);
}
@Override
/*异步操作结束时调用的回调函数 UI线程中执行
* */
protected void onPostExecute(String result) { // 最后的结果
super.onPostExecute(result);
Mylog.d("--------onPostExecute-------");
mProgressTxt.setText(result);
}
}
}
xml布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/show_progress_txt"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<SeekBar
android:id="@+id/asynctask_seekbar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/thread_start_btn"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="线程加handler方式加载进度"/>
<Button
android:id="@+id/asybctask_start_btn"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="asybctask加载进度"/>
<Button
android:id="@+id/asybctask_downloadPicture_btn"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="asybctask网路下载图片"/>
<ImageView
android:id="@+id/downloadpicture_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>