-
AsyncTask為什么要設(shè)計為只能夠一次任務(wù)寻定?
因為要同一個實例執(zhí)行多次很麻煩,沒必要缭保。
假設(shè)允許多次 execute 同一個 AsyncTask 多次蘸朋,也就是說隊列中會有同一個 AsyncTask 實例出現(xiàn)多次。首先 AsyncTask 需要改動很多韩容,比如把各種狀態(tài)額外保存多份款违,不能像現(xiàn)在這樣簡單做為 AsyncTask 的成員變量,這些先不說群凶,從調(diào)用者角度來看:
你繼承 AsyncTask 實現(xiàn)了自己的一個子類 MyTask插爹,加了一些成員變量,你想多次執(zhí)行同一個 MyTask请梢,發(fā)現(xiàn)不對啊赠尾,我第一次執(zhí)行后這些成員變量的值都變了,狀態(tài)不對毅弧。還得加個 reset 函數(shù)把這些值改回初使值气嫁,再一想何必呢,我干脆重新 new 一個 MyTask 不是更簡單有效嗎够坐。
另外寸宵,雖然用默認(rèn)的 Executor 是不會同時運行的,但你 execute 時如果用了自己定義 Executor咆霜,是有可能會多線程同時訪問的邓馒。這時你也會想還要搞線程同步太麻煩了還是我還是 new 兩個 MyTask 別想著同一個 MyTask 運行兩次好了。
所以蛾坯,你看光酣,就算人家允許你同一個 AsyncTask execute 多次,你既然也不會用這功能的話脉课,我就干脆不許你 execute 兩次好了救军。
-
AsynTask造成的內(nèi)存泄露的問題怎么解決财异,比如任務(wù)還在請求中,但這個Activity已經(jīng)被銷毀了唱遭,這個task就仍然持有act的引用戳寸,造成內(nèi)存泄露?
最主要的是在 Activity 銷毀時就應(yīng)該把所有屬于這個 Activity 的 Task cancel 掉拷泽。
你的 Task 應(yīng)該在 onCancelled 函數(shù)中做相應(yīng)的處理疫鹊。比如說如果 Task 是用 來聯(lián)網(wǎng)的,就應(yīng)該在 onCancelled 中 disconnect司致。然后在 onCancelled 中將指向 Activity 的引用設(shè)為 null;
弱引用更多的是一份保險拆吆,保證如果你在沒有正確 cancel Task 時,不會讓本應(yīng)去死的 Activity 還因為 Task 的引用還在內(nèi)存中晃悠脂矫。當(dāng)然這個保險是很有必要的枣耀。
弱引用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執(zhí)行完返回結(jié)果在已經(jīng)被銷毀的act顯示,會如何庭再?
如果執(zhí)行了這個 activity 的 view 的操作的話捞奕,會報異常。因為此時這個 view 已經(jīng)不屬于任何活的Window拄轻。
-
Act銷毀但Task如果沒有銷毀掉颅围,當(dāng)Act重啟時這個task該如何解決?
最多就是 Task 指向 Activity 的引用改成弱引用了哺眯。 Task 如果是 Activity 一個成員的話已經(jīng)泄漏無法訪問了谷浅。