AsyncTask cái tên đã nói lên tất cả. Nó cho phép chúng ta thực thi 1 task dưới background thread giúp giảm tải cho UI thread nhưng vẩn cung cấp các phương thức chúng ta có thể thao tác với UI thread một cách dễ giàng. AsyncTask củng là phương thức bất đồng bộ được sử dụng nhiều trong Android nên có thể nó không còn xa lạ gì với bạn. Nhưng có bao giờ bạn thật sự tìm hiểu sâu cơ chế thực thi của nó, nó được thực thi song song hay tuần tự hay cả hai?

Thực ra AsyncTask có thể được thực thi song song lẫn tuần tự. Chúng ta có thể chỉ định môi trường thực thi cho nó 1 cách tường minh, còn mặc định thì lại có sự khác nhau giữa các phiên bản Android. Phương thức để start 1 AsyncTask chỉ định cách mà nó sẽ được thực thi.

Execution Method Lowest API level Return value Executor BackGround Task Execution type
execute(Params…) 3 The started AsyncTask Defined in AsyncTask doInBackground Sequential or concurrent
(static) execute(Runnable) 11 None Defined in AsyncTask Runnable Sequential only
executeOnExecutor(Executor, Par ams…) 11 The started AsyncTask Customizable doInBackground Customizable

 

Trước Android 11 (HONEYCOMB) AsyncTask chỉ cung cấp 1 phương thức duy nhất execute(Params…) để thực thi 1 AsyncTask. Từ HONEYCOMB trở đi chúng ta có cả ba phương thức như trên bảng. Tuỳ từng phiên bản Android mà chúng được thực thi song song hay tuần tự (xem bảng dưới).

API level execute executeOnExecutor
1-3 Sequential Not available
4 – 10 Concurrent Not available
11 – 12 Concurrent Sequential/concurrent (customizable)
13+ Sequential Sequential/concurrent (customizable)

 

Sau đây là 1 demo nho nhỏ mình lấy từ android-er.blogspot.com để minh hoạ sự thực thi song song và tuần tự của AsyncTask.

  • giao diện chương trình đơn giản chỉ có 5 progress bar.
  • 3 progress đầu được cập nhật bới 3 AsyncTask được thực thi bằng execute().
  • 2 progress cuối được cập nhật bởi 2 AsyncTask được thực thi bằng executeOnExecutor()

MainActivity.java

<code>package com.example.androidparallelasynctask;

import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.annotation.TargetApi;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.SystemClock;

public class MainActivity extends Activity {

 public class MyAsyncTask extends AsyncTask<Void, Integer, Void> {

  ProgressBar myProgressBar;
  
  public MyAsyncTask(ProgressBar target) {
   myProgressBar = target;
  }

  @Override
  protected Void doInBackground(Void... params) {
   for(int i=0; i<100; i++){
    publishProgress(i);
    SystemClock.sleep(100);
   }
   return null;
  }

  @Override
  protected void onProgressUpdate(Integer... values) {
   myProgressBar.setProgress(values[0]);
  }

 }
 
 Button buttonStart;
 ProgressBar progressBar1, progressBar2, progressBar3, progressBar4, progressBar5;
 MyAsyncTask asyncTask1, asyncTask2, asyncTask3, asyncTask4, asyncTask5;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  progressBar1 = (ProgressBar)findViewById(R.id.progressbar1);
  progressBar2 = (ProgressBar)findViewById(R.id.progressbar2);
  progressBar3 = (ProgressBar)findViewById(R.id.progressbar3);
  progressBar4 = (ProgressBar)findViewById(R.id.progressbar4);
  progressBar5 = (ProgressBar)findViewById(R.id.progressbar5);
  
  buttonStart = (Button)findViewById(R.id.start);
  buttonStart.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    asyncTask1 = new MyAsyncTask(progressBar1);
    asyncTask1.execute();
    asyncTask2 = new MyAsyncTask(progressBar2);
    asyncTask2.execute();
    asyncTask3 = new MyAsyncTask(progressBar3);
    asyncTask3.execute();
    asyncTask4 = new MyAsyncTask(progressBar4);
    StartAsyncTaskInParallel(asyncTask4);
    asyncTask5 = new MyAsyncTask(progressBar5);
    StartAsyncTaskInParallel(asyncTask5);
   }});

 }
 
 @TargetApi(Build.VERSION_CODES.HONEYCOMB)
 private void StartAsyncTaskInParallel(MyAsyncTask task) {
     if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
         task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     else
         task.execute();
 }

}</code>

activity_main.xml

<code><LinearLayout 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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.example.androidparallelasynctask.MainActivity" >
    
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />
    
    <Button
        android:id="@+id/start"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Start"/>
    
    <ProgressBar
        android:id="@+id/progressbar1"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:progress="0" />
    <ProgressBar
        android:id="@+id/progressbar2"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:progress="0" />
    <ProgressBar
        android:id="@+id/progressbar3"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:progress="0" />
    <ProgressBar
        android:id="@+id/progressbar4"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:progress="0" />
    <ProgressBar
        android:id="@+id/progressbar5"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:progress="0" />
        
</LinearLayout></code>

tham khảo
android-er.blogspot
oreilly-efficient-android-threading-2014

Advertisements