您的位置:首页 > 其它

异步任务处理---AsyncTask

2016-03-29 22:19 239 查看
今天学习了AsyncTask的基本用法,现在进行一个总结:

首先要知道为什么异步任务:

1、Android单线程模型

2、 耗时的操作要放在非主线程中进行,避免主线程堵塞

其次要知道AsyncTask的作用:

1、在子线程中更新UI

2、封装、简化异步操作

接下来看下AsyncTask的基本用法:

由于AsyncTask是一个抽象类,所以如果我们想使用它,就必须创建一个子类去继承它,在继承时我们必须为AsyncTask类指定三个泛型参数,如果传入Void,则表示不传入参数

1、Params:在执行时传入要传入的参数,可用于在后台任务中使用

2、Progress:后台任务执行时,如果需要在界面上显示当前的进度,则使用指定的泛型作为进度单位

3、Result:当任务执行执行完毕后,如果需要对结果进行返回,使用这里指定的泛型作为返回值类型

然后我们需要构建AsyncTask子类的回调方法:

onPrexecute()执行后台操作前调用,一般执行初始化操作,在doInBackground方法前执行

doInBackground(Params…)必须重写,在这里执行异步任务;耗时操作写在这里,可调用publishProgress(Progress…)方法返回当前的执行进度

onProgressUpdate(Progress…)当在doInBackground调用doInBackground()后很快被调用对UI操作,这个可以不写(没有在doInBackground中调用)

onPostExecute(Result):当doInBackground方法结束执行,系统自动调用该方法,接收的值就是doInBackground最后返回的值;

说下使用AsyncTask的注意事项

1、必须在UI线程中创建AsyncTask实例

2、必须在UI线程中调用AsyncTask的execute()方法

3、重写的四个方法是系统自动调用的,不要手动去调用

4、每个AsyncTask只能被执行一次,多次调用将会引发异常

下面开始实例:使用AsyncTask加载图片

首选我们创建布局:image.xml用于显示图片IMageView和加载进度ProgressBar

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:padding="16dp"
android:layout_height="match_parent">

<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ProgressBar
android:id="@+id/progrssBar"
android:visibility="gone"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>


新建活动ImageTest

package com.asynctask.css.asynctask;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;//手动导入
import java.io.InputStream;
import java.net.URLConnection;

/**
* Created by css on 2016/3/28.
*/
public class ImageTest extends Activity {

private ImageView mImageView;
private ProgressBar mProgressBar;
MyAsynvTask mtask;

//定义静态的String类型的URL用于存储要加载图片的地址
private static String URL = "http://pic.mmfile.net/2013/08/1315595G7-2.jpg";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.image);
mImageView = (ImageView) findViewById(R.id.image);
mProgressBar = (ProgressBar) findViewById(R.id.progrssBar);

//当调用execute之后,进行异步操作
mtask = new MyAsynvTask();
mtask.execute(URL);

}
//    新建内部类MyAsynvTask继承AsyncTask,设置传递进去的参数,
//    1、第一个参数表示加载图片的地址,所以传入String,
//    2、第二个参数表示不需要显示返回进度,使用Void,
//    3、第三个参数表示最后返回Bitmap
class MyAsynvTask extends AsyncTask<String,Void,Bitmap>
{
//      1、系统调用该方法,对异步操作进行初始化操作,这里显示ProgressBar
@Override
protected void onPreExecute() {
super.onPreExecute();
mProgressBar.setVisibility(View.VISIBLE);
}

//      2、开始真正的异步操作处理,都在子线程中处理,放置任意的耗时操作,最后返回指定的类型
@Override
protected Bitmap doInBackground(String... params) {
String url = params[0];//可以传递不止一个参数进来,以数组的形式存在,取出对应的URL
Bitmap bitmap = null;

URLConnection connection ;  //定义网络连接对象
InputStream is;             //用于获取数据的输入流
//访问网络的费时操作
try {
connection = new URL(url).openConnection(); //此处需要手动导入URL包,获取网络连接对象
is = connection.getInputStream();           //获取输入流
BufferedInputStream bis = new BufferedInputStream(is);
//加入睡眠时间,晚点执行
//                try {
//                    Thread.sleep(3000);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//使用BitmapFactory的decodeStream方法可以很方便的把bis输入流转换为Bitmap
bitmap = BitmapFactory.decodeStream(bis);
is.close();//关闭输入流
bis.close();
}
catch (IOException e)
{
e.printStackTrace();
}
//将bitmap作为返回值传递到onPostExecute中,在onPostExecute进行UI更新
return bitmap;
}

//      3、运行在主线程,任意进行UI操作onPostExecute在本方法中操作UI,把图像设置到ImageView
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
mProgressBar.setVisibility(View.GONE);  //隐藏ProgressBar
mImageView.setImageBitmap(bitmap);      //显示图片
}
}
}


写完活动之后立马注册活动,养成好习惯;

<activity android:name=".ImageTest"></activity>


最后在主活动里面点击Button实现加载图片,剩下的点击Button就省略了,很简单。

看下运行效果:

1、MainActivity主界面



2、加载过程中ProgressBar显示界面



3、加载成功图片显示界面



最后说下AsyncTask的取消:

AsyncTaskc是通过线程池执行的,如果前面的线程没有执行完,再去点击开启一个新的线程的时候就会出现空白,即新线程并没有执行,而是等待上一个线程执行完之后才开始执行的;那么怎么解决这个问题呢?

需要通过让AsyncTask的声明周期和activity的声明周期保持一致,在activity的onpause方法中加入如下代码:

@Override
protected void onPause() {
super.onPause();
if (mTask != null && mTask.getStatus() == AsyncTask.Status.RUNNING)
{
//cancel方法只是将AsyncTask标记为cancel状态,并不是真正的取消线程的执行
mTask.cancel(true);
}
}


仅仅写这些事不够的,因为.cancel方法只是对该线程进行标示,并没有取消该线程,还要加上下面的代码

if(isCancelled())
{
break;
}


具体的参考代码,下载地址:AsyncTask小例子
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: