之前封装过很多工具类,一直没有整理,结果回过头要用的时候往往找起来很麻烦。一直想整理一下,结果不是没时间就是懒,不是懒就是没时间。今天群里有人问到AsyncTask,于是乎,我冒出个想法。封装一下AsyncTask,也方便我以后的使用。以前都没有图,今天没图怎么行呢,据说上图能提升某格。所以我也上图,而且是好图,多年珍藏的好图。
先简单介绍一下AsyncTask。
AsyncTask有三个泛型AsyncTask<Params, Progress, Result>,三种泛型分别代表“启动任务执行时的参数”、“任务执行的进度”、“任务执行的结果类型”。在很多时候,并不是所有类型都被使用,如果没有被使用,可以用Void类型代替。我通常的用法是AsyncTask<Void, Void, Result>,恨不得返回类型也是Void。可惜,人生无奈之事十有八九,此为其一。。
一个异步任务的执行一般包括以下几个步骤:
1.execute(Params... params),执行一个异步任务,需要我们在代码中调用此方法,触发异步任务的执行。
2.onPreExecute(),在execute(Params... params)被调用后立即执行,一般用来在执行后台任务前对UI做一些标记。
3.doInBackground(Params... params),在onPreExecute()完成后立即执行,用于执行较为费时的操作,此方法将接收输入参数和返回计算结果。在执行过程中可以调用publishProgress(Progress... values)来更新进度信息。
4.onProgressUpdate(Progress... values),在调用publishProgress(Progress... values)时,此方法被执行,直接将进度信息更新到UI组件上。
5.onPostExecute(Result result),当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法中,直接将结果显示到UI组件上。
在使用的时候,有几点需要格外注意:
1.异步任务的实例必须在UI线程中创建。
2.execute(Params... params)方法必须在UI线程中调用。
3.不要手动调用onPreExecute(),doInBackground(Params... params),onProgressUpdate(Progress... values),onPostExecute(Result result)这几个方法。
4.不能在doInBackground(Params... params)中更改UI组件的信息。
5.一个任务实例只能执行一次,如果执行第二次将会抛出异常。
看着很头疼,想起来更头疼,就连江湖人称玉树临风赛潘安,两朵菊花压海棠的起猿猩猩也深表无奈。无奈归无奈,封装走起。
看懂了上面的AsyncTask的执行过程,下面的代码就小kiss啦。
封装好的AsyncLoader类。
import android.os.AsyncTask;
/**
*
* @Description:异步数据加载器
* <p>创建日期:2013-9-3 </p>
* @version V1.0
* @author LZP
* @see
*/
public class AsyncLoader<P, S, T> extends AsyncTask<P, S, T> {
private OnLoadListener<P, S, T> mListener;
private int mDataType;
private Exception ex;
public AsyncLoader(int dataType) {
mDataType = dataType;
mListener = new OnLoadListener<P, S, T>() {
@Override
public void onDataStart() {
}
@Override
public T doInWorkerThread(int dataType, P... params)
throws Exception {
return null;
}
@Override
public void onDataGet(T result) {
}
@Override
public void onDataFail(Exception e) {
}
@Override
public void onDataFinish() {
}
@Override
public void onDataProgress(S... values) {
}
};
}
public void setOnLoadListener(OnLoadListener<P, S, T> listener) {
if (listener != null) {
mListener = listener;
}
}
@Override
protected void onPreExecute() {
super.onPreExecute();
mListener.onDataStart();
}
@Override
protected T doInBackground(P... params) {
try {
return (T) mListener.doInWorkerThread(mDataType,params);
} catch (Exception e) {
e.printStackTrace();
ex = e;
return null;
}
}
@Override
protected void onProgressUpdate(S... values) {
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(T result) {
super.onPostExecute(result);
if (ex != null) {
mListener.onDataFail(ex);
} else {
mListener.onDataGet(result);
}
mListener.onDataFinish();
}
@Override
protected void onCancelled() {
super.onCancelled();
mListener.onDataFinish();
}
/**
*
* @Description:异步数据回调接口类
* <p>创建日期:2013-9-3 </p>
* @version V1.0
* @author LZP
* @see
*/
public interface OnLoadListener<P, S, T> {
/**
*
* @Description:异步数据加载开始时回调
* <p>创建人:LZP , 2013-9-3 下午9:42:58</p>
* <p>修改人:LZP , 2013-9-3 下午9:42:58</p>
*
*
*/
void onDataStart();
/**
*
* @Description:异步数据请求回调,运行子线程中
* <p>创建人:LZP , 2013-9-3 下午9:43:21</p>
* <p>修改人:LZP , 2013-9-3 下午9:43:21</p>
*
* @param dataType
* @return
* @throws Exception
*
*/
T doInWorkerThread(int dataType,P... params) throws Exception;
/**
*
* @Description:异步数据进行的进度回调,用来显示进度条或更新UI等
* <p>创建人:LZP , 2013-9-3 下午9:43:21</p>
* <p>修改人:LZP , 2013-9-3 下午9:43:21</p>
*
* @param values
* @return
* @throws Exception
*
*/
void onDataProgress(S... values);
/**
*
* @Description:异步数据返回时回调
* <p>创建人:LZP , 2013-9-3 下午9:43:59</p>
* <p>修改人:LZP , 2013-9-3 下午9:43:59</p>
*
* @param result
* void
*/
void onDataGet(T result);
/**
*
* @Description:异步数据请求失败时回调
* <p>创建人:LZP , 2013-9-3 下午9:44:21</p>
* <p>修改人:LZP , 2013-9-3 下午9:44:21</p>
*
* @param e
* void
*/
void onDataFail(Exception e);
/**
*
* @Description:异步数据结束时回调
* <p>创建人:LZP , 2013-9-3 下午9:44:43</p>
* <p>修改人:LZP , 2013-9-3 下午9:44:43</p>
*
* void
*/
void onDataFinish();
}
}
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import com.common.asynctask.AsyncLoader;
import com.common.asynctask.AsyncLoader.OnLoadListener;
import android.R.integer;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
public class MainActivity extends Activity implements OnClickListener,OnLoadListener<Void, Integer, Bitmap>{
private Button mButton;
private ImageView mImageView;
private AsyncLoader<Void, Integer, Bitmap> mLoader;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
initView();
}
private void initView() {
mButton = (Button) findViewById(R.id.button);
mImageView = (ImageView) findViewById(R.id.iv);
mButton.setOnClickListener(this);
}
/**
* 执行异步任务
* @param dataType 用来区分不同异步任务
*/
private void loadData(int dataType) {
mLoader = new AsyncLoader<Void, Integer, Bitmap>(dataType);
mLoader.setOnLoadListener(this);
mLoader.execute();
}
//-----------------------------华丽的分割线---------------------------------------
@Override
public void onDataStart() {
Log.i("mainactivity", "开始异步任务");
}
@Override
public Bitmap doInWorkerThread(int dataType, Void... params)
throws Exception {
return returnBitMap("http://c.hiphotos.baidu.com/image/pic/item/6c224f4a20a446234b87678d9a22720e0df3d794.jpg");
}
//调用publishProgress()方法,才会执行此方法
@Override
public void onDataProgress(Integer... values) {
Log.i("mainactivity", ""+values);
}
@Override
public void onDataGet(Bitmap result) {
Log.i("mainactivity", "获得异步任务结果");
mImageView.setImageBitmap(result);
}
@Override
public void onDataFail(Exception e) {
Log.i("mainactivity", "异步任务失败");
}
@Override
public void onDataFinish() {
Log.i("mainactivity", "结束异步任务");
}
//-----------------------------华丽的分割线---------------------------------------
@Override
public void onClick(View v) {
loadData(1);
}
/**
* 网络下载图片的方法
* @param url 图片地址
* @return
*/
private Bitmap returnBitMap(String url) {
URL imUrl = null;
Bitmap bitmap = null;
try {
imUrl = new URL(url);
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
HttpURLConnection conn = (HttpURLConnection) imUrl.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
bitmap = BitmapFactory.decodeStream(is);
is.close();
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
}
虽然没简化多少,不过方法很清晰。大家有啥好的建议随时更新哈。
转载请注明出处。