在如何使用AsyncTask-實作中實作了一個簡單的AsyncTask範例,
但是在如何使用AsyncTask中表示實作多個任務會讓共用的ThreadPool產生阻塞(blocking),
因此AsyncTask允許你自訂自己的執行器。
而我們知道AsyncTask執行有兩種形式,
在API 13以後, 預設是循序的,
實際上你也可以改用並行的。
//循序
executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, parameter);
//並行
executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, parameter);
但是這樣一來仍然是使用公用的執行器, 仍然會阻塞問題,
因此要把兩個結合起來,
當你想循序, 可以自訂執行器為single。
executeOnExecutor(Executors.newSingleThreadExecutor(), parameter);
反之, 並行可以宣告多個Thread的ThreadPool。
executeOnExecutor(Executors.newCachedThreadPool(), parameter);
下面用如何使用AsyncTask-實作的例子來改寫。
使用兩個TextView, 跟一個Button,
當按下Button的時候, 並行兩個任務, 並且把結果顯示在TextView上面。
<?xml version="1.0" encoding="utf-8"?>
<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" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<Button
android:id="@+id/send_task"
android:text="send task"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_below="@id/send_task"
android:id="@+id/message"
android:text="Hello World!"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_below="@id/message"
android:id="@+id/message_2"
android:text="Hello World!"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
接著都是相同方式,
只是多了一個index來判斷是第一個任務還是第二個任務,
目的來表示他真的是並發執行。
public class MainActivity extends AppCompatActivity {
private Button sendTask;
private TextView msg, msg2;
private StringBuffer stringBuffer, stringBuffer2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();
}
private void initData(){
stringBuffer = new StringBuffer();
stringBuffer2 = new StringBuffer();
}
private void initView(){
sendTask = (Button) findViewById(R.id.send_task);
msg = (TextView) findViewById(R.id.message);
msg2 = (TextView) findViewById(R.id.message_2);
sendTask.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getTask(1, "a", "b", "c", "d", "e");
getTask(2, "f", "g", "h", "i", "j");
}
});
}
private AsyncTask<String, Integer, String[]> getTask(final int index, String... name){
stringBuffer.delete(0, stringBuffer.length());
stringBuffer2.delete(0, stringBuffer2.length());
return new AsyncTask<String, Integer, String[]>() {
private int count;
@Override
protected String[] doInBackground(String... params) {
for(String s : params) {
try {
int rand = (int)(Math.random()*3 + 1);
Thread.sleep(rand * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
publishProgress(count, params.length);
count++;
}
return params;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
int percent = (int)(100 / values[1] * count);
if(index == 1) {
msg.setText(percent + "%");
} else{
msg2.setText(percent + "%");
}
}
@Override
protected void onPostExecute(String[] s) {
super.onPostExecute(s);
for(String str : s) {
if(index == 1) {
stringBuffer.append(str).append("\n");
msg.setText(stringBuffer);
} else{
stringBuffer2.append(str).append("\n");
msg2.setText(stringBuffer2);
}
}
}
}.executeOnExecutor(Executors.newCachedThreadPool(), name);
}
}
結果如下
程式碼