-
AsyncTask為什么要設計為只能夠一次任務?
因為要同一個實例執行多次很麻煩,沒必要。
假設允許多次 execute 同一個 AsyncTask 多次,也就是說隊列中會有同一個 AsyncTask 實例出現多次。首先 AsyncTask 需要改動很多,比如把各種狀態額外保存多份,不能像現在這樣簡單做為 AsyncTask 的成員變量,這些先不說,從調用者角度來看:
你繼承 AsyncTask 實現了自己的一個子類 MyTask,加了一些成員變量,你想多次執行同一個 MyTask,發現不對啊,我第一次執行后這些成員變量的值都變了,狀態不對。還得加個 reset 函數把這些值改回初使值,再一想何必呢,我干脆重新 new 一個 MyTask 不是更簡單有效嗎。
另外,雖然用默認的 Executor 是不會同時運行的,但你 execute 時如果用了自己定義 Executor,是有可能會多線程同時訪問的。這時你也會想還要搞線程同步太麻煩了還是我還是 new 兩個 MyTask 別想著同一個 MyTask 運行兩次好了。
所以,你看,就算人家允許你同一個 AsyncTask execute 多次,你既然也不會用這功能的話,我就干脆不許你 execute 兩次好了。
-
AsynTask造成的內存泄露的問題怎么解決,比如任務還在請求中,但這個Activity已經被銷毀了,這個task就仍然持有act的引用,造成內存泄露?
最主要的是在 Activity 銷毀時就應該把所有屬于這個 Activity 的 Task cancel 掉。
你的 Task 應該在 onCancelled 函數中做相應的處理。比如說如果 Task 是用 來聯網的,就應該在 onCancelled 中 disconnect。然后在 onCancelled 中將指向 Activity 的引用設為 null;
弱引用更多的是一份保險,保證如果你在沒有正確 cancel Task 時,不會讓本應去死的 Activity 還因為 Task 的引用還在內存中晃悠。當然這個保險是很有必要的。
弱引用Demo:
static class AsyncDrawable extends BitmapDrawable {
private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;
public AsyncDrawable(Resources res, Bitmap bitmap,
BitmapWorkerTask bitmapWorkerTask) {
super(res, bitmap);
bitmapWorkerTaskReference =
new WeakReference<BitmapWorkerTask>(bitmapWorkerTask);
}
public BitmapWorkerTask getBitmapWorkerTask() {
return bitmapWorkerTaskReference.get();
}
}
public void loadBitmap(int resId, ImageView imageView) {
if (cancelPotentialWork(resId, imageView)) {
final BitmapWorkerTask task = new BitmapWorkerTask(imageView);
final AsyncDrawable asyncDrawable =
new AsyncDrawable(getResources(), mPlaceHolderBitmap, task);
imageView.setImageDrawable(asyncDrawable);
task.execute(resId);
}
}
public static boolean cancelPotentialWork(int data, ImageView imageView) {
final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
if (bitmapWorkerTask != null) {
final int bitmapData = bitmapWorkerTask.data;
// If bitmapData is not yet set or it differs from the new data
if (bitmapData == 0 || bitmapData != data) {
// Cancel previous task
bitmapWorkerTask.cancel(true);
} else {
// The same work is already in progress
return false;
}
}
// No task associated with the ImageView, or an existing task was cancelled
return true;
}
private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
if (imageView != null) {
final Drawable drawable = imageView.getDrawable();
if (drawable instanceof AsyncDrawable) {
final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
return asyncDrawable.getBitmapWorkerTask();
}
}
return null;
}
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
...
@Override
protected void onPostExecute(Bitmap bitmap) {
if (isCancelled()) {
bitmap = null;
}
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get();
final BitmapWorkerTask bitmapWorkerTask =
getBitmapWorkerTask(imageView);
if (this == bitmapWorkerTask && imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}
-
task執行完返回結果在已經被銷毀的act顯示,會如何?
如果執行了這個 activity 的 view 的操作的話,會報異常。因為此時這個 view 已經不屬于任何活的Window。
-
Act銷毀但Task如果沒有銷毀掉,當Act重啟時這個task該如何解決?
最多就是 Task 指向 Activity 的引用改成弱引用了。 Task 如果是 Activity 一個成員的話已經泄漏無法訪問了。