AsyncTask在概念上是否真的有缺陷,還是我只是遺漏了什么?我已經(jīng)調(diào)查了這個(gè)問題幾個(gè)月了,想出了不同的解決方案,我對(duì)此并不滿意,因?yàn)樗鼈兌际谴笠?guī)模的黑客。我仍然不能相信,一個(gè)在設(shè)計(jì)上有缺陷的類把它納入了框架,沒有人在談?wù)撍?,所以我想我一定是遺漏了什么。問題在于AsyncTask..根據(jù)文件“允許在UI線程上執(zhí)行后臺(tái)操作和發(fā)布結(jié)果,而不必操作線程和/或處理程序。”然后,該示例將繼續(xù)展示一些示例性的showDialog()方法被調(diào)用為onPostExecute()..然而,這似乎完全人為的對(duì)我來說,因?yàn)轱@示對(duì)話框總是需要引用一個(gè)有效的Context,以及AsyncTask絕不能持有對(duì)上下文對(duì)象的強(qiáng)引用。.原因很明顯:如果活動(dòng)被破壞,從而觸發(fā)了任務(wù),該怎么辦?這可以隨時(shí)發(fā)生,例如,因?yàn)槟惴D(zhuǎn)了屏幕。如果任務(wù)將保存對(duì)創(chuàng)建它的上下文的引用,則不僅保留無用的上下文對(duì)象(窗口將被銷毀,而且任何UI交互將失敗,除非有例外!),您甚至有可能造成內(nèi)存泄漏。除非我的邏輯在這里有缺陷,否則這意味著:onPostExecute()這是完全無用的,因?yàn)槿绻鷽]有訪問任何上下文的權(quán)限,在UI線程上運(yùn)行這個(gè)方法又有什么好處呢?你不能在這里做任何有意義的事。解決方法之一是不將上下文實(shí)例傳遞給AsyncTask,而是將Handler舉個(gè)例子。這是可行的:因?yàn)镠andler松散地綁定了上下文和任務(wù),所以您可以在它們之間交換消息,而不會(huì)冒泄漏的風(fēng)險(xiǎn)(對(duì)嗎?)但這意味著AsyncTask的前提,即不需要處理程序,是錯(cuò)誤的。這似乎也是濫用Handler,因?yàn)槟谕粋€(gè)線程上發(fā)送和接收消息(在UI線程上創(chuàng)建消息,并在onPostExecute()中通過它發(fā)送消息,onPostExecute()也是在UI線程上執(zhí)行的)。更重要的是,即使有了這種解決辦法,您仍然存在這樣的問題:當(dāng)上下文被破壞時(shí),您仍然會(huì)遇到這樣的問題。無記錄它發(fā)射的任務(wù)。這意味著在重新創(chuàng)建上下文時(shí),您必須重新啟動(dòng)任何任務(wù),例如,在屏幕方向改變之后。這既慢又浪費(fèi)。我對(duì)此的解決方案(如在Droid-Fu庫中實(shí)現(xiàn))是維護(hù)WeakReference從組件名稱到其在唯一應(yīng)用程序?qū)ο笊系漠?dāng)前實(shí)例。每當(dāng)AsyncTask啟動(dòng)時(shí),它都會(huì)在該映射中記錄調(diào)用上下文,并且在每次回調(diào)時(shí),它將從該映射中獲取當(dāng)前上下文實(shí)例。這確保您永遠(yuǎn)不會(huì)引用陳舊的上下文實(shí)例。和在回調(diào)中,您始終可以訪問有效的上下文,這樣就可以在那里完成有意義的UI工作。它也不會(huì)泄漏,因?yàn)橐檬侨醯?,并且在給定組件的實(shí)例不再存在時(shí)被清除。不過,這是一個(gè)復(fù)雜的解決方案,需要對(duì)Droid-Fu庫類進(jìn)行子類處理,這使其成為一種相當(dāng)有侵?jǐn)_性的方法?,F(xiàn)在我只想知道:我只是大量地遺漏了一些東西,還是AsyncTask真的完全有缺陷?你的工作經(jīng)驗(yàn)如何?你是怎么解決這些問題的?謝謝你的意見。
3 回答

烙印99
TA貢獻(xiàn)1829條經(jīng)驗(yàn) 獲得超13個(gè)贊
class MyActivity extends Activity { Worker mWorker; static class Worker extends AsyncTask<URL, Integer, Long> { MyActivity mActivity; Worker(MyActivity activity) { mActivity = activity; } @Override protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) ((i / (float) count) * 100)); } return totalSize; } @Override protected void onProgressUpdate(Integer... progress) { if (mActivity != null) { mActivity.setProgressPercent(progress[0]); } } @Override protected void onPostExecute(Long result) { if (mActivity != null) { mActivity.showDialog("Downloaded " + result + " bytes"); } } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mWorker = (Worker)getLastNonConfigurationInstance(); if (mWorker != null) { mWorker.mActivity = this; } ... } @Override public Object onRetainNonConfigurationInstance() { return mWorker; } @Override protected void onDestroy() { super.onDestroy(); if (mWorker != null) { mWorker.mActivity = null; } } void startWork() { mWorker = new Worker(this); mWorker.execute(...); }}

ibeautiful
TA貢獻(xiàn)1993條經(jīng)驗(yàn) 獲得超6個(gè)贊
原因很明顯:如果活動(dòng)被破壞,從而觸發(fā)了任務(wù),該怎么辦?
AsyncTask
onDestroy()
AsyncTask
onCreate()
- 3 回答
- 0 關(guān)注
- 382 瀏覽
添加回答
舉報(bào)
0/150
提交
取消