Java多线程之异步任务——AsyncTask

来源:互联网 发布:获取data-tab数据 编辑:程序博客网 时间:2024/05/13 10:46
为什么需要异步任务?
1、Android单线程模型
2、耗时操作放在非主线程中执行

AsyncTask为何而生?
1、子线程中更新UI
2、封装、简化异步操作

构建AsyncTask子类的参数
AsyncTask<Params,Progress,Result>是一个抽象类,通常用于被继承,继承AsyncTask需要制定如下三个泛型参数:
Params:启动任务是输入参数的类型。
Progress:后台任务执行中返回进度值的类型。
Result:后台执行任务完成后返回结果的类型。


构建AsyncTask子类的回调方法:
doInBackground:
必须重写,异步执行后台线程将要完成的任务;
onPreExecute:执行后台耗时操作前调用,通常用户完成一些初始化操作;
onPostExecute:当doInBackground()完成后,系统会自动调用onPostExecute()方法,并将doInBackground()方法返回的值传给该方法;
onProgressUpdate:在doInBackground()方法中调用publishProgress()方法更新任务的执行进度后,就会触发该方法。

回调方法的执行顺序:
onPreExecute() -> doInBackground() -> onPostExecute()

在doInBackground()方法中调用publishProgress()方法更新任务的执行进度:
onPreExecute() -> doInBackground() -> onProgressUpdate() -> onPostExecute()

完成初始化操作       完成耗时操作              更新进度条                得到doInBackground的返回值进行处理


接下来新建一个Android项目测试一下,新建Android项目之后,直接添加一个MyAsyncTask类:

public class MyAsyncTask extends AsyncTask<Void, Void, Void> {private static final String TAG = "MyAsyncTask";@Overrideprotected Void doInBackground(Void... arg0) {Log.e(TAG, "****doInBackground****");publishProgress();return null;}@Overrideprotected void onPostExecute(Void result) {Log.e(TAG, "****onPostExecute****");super.onPostExecute(result);}@Overrideprotected void onPreExecute() {Log.e(TAG, "****onPreExecute****");super.onPreExecute();}@Overrideprotected void onProgressUpdate(Void... values) {Log.e(TAG, "****onProgressUpdate****");super.onProgressUpdate(values);}}

而后在MainActivity.java里面new一个MyAsyncTask类,并调用execute()方法:

public class MainActivity extends ActionBarActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);MyAsyncTask task = new MyAsyncTask();task.execute();}}

运行查看Log打印情况:


根据打印的Log,我们可以发现四个方法的运行顺序。

接下来我们修改一下并继续编写项目,简单的使用一下AsyncTask。

MyAsyncTask类:

public class MyAsyncTask extends AsyncTask<String, Void, Bitmap> {private static final String TAG = "MyAsyncTask";private ImageView imageView;public MyAsyncTask(ImageView imageView){this.imageView = imageView;}@Overrideprotected Bitmap doInBackground(String... arg0) {Log.e(TAG, "****doInBackground****");publishProgress();//获取传递进来的参数String url = arg0[0];Bitmap bitmap = null;URLConnection connection;InputStream is;try {connection = new URL(url).openConnection();is = connection.getInputStream();BufferedInputStream bis = new BufferedInputStream(is);//通过decodeStream解析输入流bitmap = BitmapFactory.decodeStream(bis);is.close();bis.close();} catch (IOException e) {e.printStackTrace();}//将Bitmap作为返回值return bitmap;}@Overrideprotected void onPostExecute(Bitmap bitmap) {Log.e(TAG, "****onPostExecute****");imageView.setImageBitmap(bitmap);super.onPostExecute(bitmap);}@Overrideprotected void onPreExecute() {Log.e(TAG, "****onPreExecute****");super.onPreExecute();}@Overrideprotected void onProgressUpdate(Void... values) {Log.e(TAG, "****onProgressUpdate****");super.onProgressUpdate(values);}}


MainActivity类:

public class MainActivity extends ActionBarActivity {private final String URL = "https://www.baidu.com/img/bd_logo1.png";private ImageView imageView1;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);imageView1 = (ImageView) findViewById(R.id.imageView1);MyAsyncTask task = new MyAsyncTask(imageView1);task.execute(URL);}}


activity_main.xml布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.itman.asynctaskdemo.MainActivity" >    <ImageView        android:id="@+id/imageView1"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerHorizontal="true"        android:layout_centerVertical="true"        android:src="@drawable/ic_launcher" /></RelativeLayout>

别忘记添加网络访问权限,最后运行项目,结果如下图:




异步任务---AsyncTask使用的注意事项:
1、必须在UI线程中创建AsyncTask的实例
2、必须在UI线程中调用AsyncTask的execute()方法
3、重写的四个方法是系统自动调用的,不应手动调用
4、每个AsyncTask只能被执行一次,多次调用将会引发异常(尤其注意