您的位置:首页 > 移动开发 > Android开发

Android基础之AsyncTask详解,巨细哟

2016-05-27 17:11 423 查看
构建AsyncTask子类参数
因为他是一个抽象类所有继承他之后需要重写下面三个泛型参数
Params:启动任务时,输入参数的类型。
Progress:后台任务执行中返回进度值的类型
Result:后台执行任务完成后返回结果的类型

构建AsyncTask子类的回调方法
dolnBackground:必须重写,异步执行后台程序将要完成的任务。
onPreExecute:执行后台耗时操作前被调用,用户通常会做一些准备工作,如一些初始化的操作。
onPostExecute():当dolnBackground()完成后,系统会自动调用该方法,并将dolnBackground()方法的返回值传给该方法。顾名思义就是展示我们所处理完的一个结果。
onProgressUpdate():在dolnBackground()方法中调用publishProgress()方法更新任务就会触发该方法。

程序的调动顺序是:
onPreExecute——>dolnBackground——>onPostExecute(没有调用publishProgress ())

传递进度:在dolnBackground()中调用publishProgress()方法的时候,就可以将一个进度值作为一参数传给onProgressUpdate(),我们就可以在onProgressUpdate()中得到这个参数,从而应用于更新一个异步进程的完成进度。

实例:
下载图片,并且显示(只是下载到缓存中。程序kill后需要再次下载)
package com.example.administrator.android_asynctask;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import java.net.URL;
import java.net.URLConnection;

/**
* Created by Administrator on 2016/5/26.
*/
public class ImageTestextends Activity {
private ImageView
imageView;
private ProgressBar
progressBar;
private static String
URL = "http://img4.duitang.com/uploads/item/201308/10/20130810135200_tyE55.jpeg";

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.image);
imageView = (ImageView) findViewById(R.id.imageView1);
progressBar = (ProgressBar) findViewById(R.id.pb);
new MyAsyncTask_1().execute(URL);

}

class MyAsyncTask_1
extends AsyncTask<String, Void, Bitmap> {
@Override
//在doInBackground启动前 ,显示progressBar
protected void onPreExecute() {
super.onPreExecute();
progressBar.setVisibility(View.VISIBLE);

}

@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
//隐藏progressBar
progressBar.setVisibility(View.GONE);
//传递bimap
imageView.setImageBitmap(bitmap);

Log.d("xyx","onPostExecute_bitmap=" + bitmap);

}

@Override
//参数是可变长数组
//<URL类型,进度值类型,返回值类型>
//doInBackground方法是开启一个异步线程做耗时操作的
protected Bitmap doInBackground(String... params) {
//取出对应的URL
String url = params[0];

Bitmap bitmap = null;

Log.d("xyx","url=" + url);
//定义网络链接对象
//以前的
// URLConnection connection;
HttpURLConnection connection;
//用于获取的数据的输入流
InputStream inputStream = null;
try {
//通过openConnection方法获取connection对象,获取网络连接对象
Thread.sleep(3000);
//原来方法
// connection = new URL(url).openConnection();
connection = (HttpURLConnection) new URL(url).openConnection();

connection.setDoInput(true);

connection.setRequestMethod("GET");

connection.connect();
//获取一个输入流
inputStream = connection.getInputStream();

BufferedInputStream bis = new BufferedInputStream(inputStream);
//通过,decodeStream解析输入流流
bitmap = BitmapFactory.decodeStream(bis);

inputStream.close();

bis.close();

} catch (IOException e) {

e.printStackTrace();

} catch (InterruptedException e) {

e.printStackTrace();

}
return bitmap;

}

}

}

模拟进度条
package com.example.administrator.android_asynctask;

import android.app.Activity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.ProgressBar;
import android.widget.TextView;

import java.util.List;

/**
 * Created by Administrator on 2016/5/27.
 */
public class progressBarTest extends Activity {

    private ProgressBar pb;

    private TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.progress);

        pb= (ProgressBar) findViewById(R.id.pb2);

        new MyAsyncTask_ProgressBar().execute();

    }

    class MyAsyncTask_ProgressBar extends AsyncTask<Void, Integer, Void> {

        @Override
        protected Void doInBackground(Void... params) {

            for (int i = 0; i <=100; i++) {

                try {

                    Thread.sleep(300);

                    publishProgress(i);

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

            }

            return null;

        }

        @Override
        protected void onProgressUpdate(Integer... values) {

            super.onProgressUpdate(values);

            pb.setProgress(values[0]);

        }

    }

}

取消AsyncTask

AsyncTask机制:因为他的底层是线程池 ,所有多次开始——返回后,他会卡住只有等之前的Task全部完成后,才会开始新的Task,而且,我们doInBackground中用的是for循环,所以只有等for循环结束,才会去执行下一个Task;所以会造成,多次进入后,进度条就会卡住的BUG,如何解决呢?
方案:

AsyncTask和Activaty的生命周期保持一致,也就是Activity生命周期走到onPause的时候,把AsyncTask干掉就好了。

package com.example.administrator.android_asynctask;

import android.app.Activity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.ProgressBar;
import android.widget.TextView;

import java.util.List;

/**
* Created by Administrator on 2016/5/27.
*/
public class progressBarTest extends Activity {
private ProgressBar pb;
private TextView tv;
private MyAsyncTask MTP;
MyAsyncTask_ProgressBar mb = new MyAsyncTask_ProgressBar();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.progress);
pb = (ProgressBar) findViewById(R.id.pb2);
mb.execute();
}

protected void onPause() {
super.onPause();
if ((mb != null) && (mb.getStatus() == AsyncTask.Status.RUNNING)) {
//这只是把MTP标记为cancel状态,不是真正的取消了线程,那我就需要,
// 给doInBackground中的for循环设定判断条件,
// 并且给onProgressUpdate进行判断是否要更新
mb.cancel(true);
}
}

class MyAsyncTask_ProgressBar extends AsyncTask<Void, Integer, Void> {
@Override
protected Void doInBackground(Void... params) {
for (int i = 0; i <= 100; i++) {
//是否有cancel状态
if (isCancelled()) {
break;
}
try {
Thread.sleep(300);
publishProgress(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}

@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
if (isCancelled()) {
return;
}
pb.setProgress(values[0]);

}
}

}


失败原因:
下载部分:
内部类是要放在外部类里面的
图片无法显示的原因:bitmap通过bitmap = BitmapFactory.decodeStream(bis);这方法无法获得bitmap值;
解决办法,网址有问题,不是图片网址
附带博客一个,解决其他问题:http://blog.csdn.net/andypan1314/article/details/6670320

     

总结:
 必须在UI线程中创建AsyncTask的实例
必须在UI线程中调用AsyncTask的execute()方法
重写的四个方法是系统自动调用的,不应手动调用
每个AsyncTask只能被执行一次,多次调用将会引发异常
dolnBackground只有这方法是在其他线程的,其他方法都是在UI线程。
     
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: