之前封装过很多工具类,一直没有整理,结果回过头要用的时候往往找起来很麻烦。一直想整理一下,结果不是没时间就是懒,不是懒就是没时间。今天群里有人问到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; } }
转载请注明出处。
源码传送门