AsyncTask在概念上是否真的有缺陷,还是我只是遗漏了什么?我已经调查了这个问题几个月了,想出了不同的解决方案,我对此并不满意,因为它们都是大规模的黑客。我仍然不能相信,一个在设计上有缺陷的类把它纳入了框架,没有人在谈论它,所以我想我一定是遗漏了什么。问题在于AsyncTask..根据文件“允许在UI线程上执行后台操作和发布结果,而不必操作线程和/或处理程序。”然后,该示例将继续展示一些示例性的showDialog()方法被调用为onPostExecute()..然而,这似乎完全人为的对我来说,因为显示对话框总是需要引用一个有效的Context,以及AsyncTask绝不能持有对上下文对象的强引用。.原因很明显:如果活动被破坏,从而触发了任务,该怎么办?这可以随时发生,例如,因为你翻转了屏幕。如果任务将保存对创建它的上下文的引用,则不仅保留无用的上下文对象(窗口将被销毁,而且任何UI交互将失败,除非有例外!),您甚至有可能造成内存泄漏。除非我的逻辑在这里有缺陷,否则这意味着:onPostExecute()这是完全无用的,因为如果您没有访问任何上下文的权限,在UI线程上运行这个方法又有什么好处呢?你不能在这里做任何有意义的事。解决方法之一是不将上下文实例传递给AsyncTask,而是将Handler举个例子。这是可行的:因为Handler松散地绑定了上下文和任务,所以您可以在它们之间交换消息,而不会冒泄漏的风险(对吗?)但这意味着AsyncTask的前提,即不需要处理程序,是错误的。这似乎也是滥用Handler,因为您在同一个线程上发送和接收消息(在UI线程上创建消息,并在onPostExecute()中通过它发送消息,onPostExecute()也是在UI线程上执行的)。更重要的是,即使有了这种解决办法,您仍然存在这样的问题:当上下文被破坏时,您仍然会遇到这样的问题。无记录它发射的任务。这意味着在重新创建上下文时,您必须重新启动任何任务,例如,在屏幕方向改变之后。这既慢又浪费。我对此的解决方案(如在Droid-Fu库中实现)是维护WeakReference从组件名称到其在唯一应用程序对象上的当前实例。每当AsyncTask启动时,它都会在该映射中记录调用上下文,并且在每次回调时,它将从该映射中获取当前上下文实例。这确保您永远不会引用陈旧的上下文实例。和在回调中,您始终可以访问有效的上下文,这样就可以在那里完成有意义的UI工作。它也不会泄漏,因为引用是弱的,并且在给定组件的实例不再存在时被清除。不过,这是一个复杂的解决方案,需要对Droid-Fu库类进行子类处理,这使其成为一种相当有侵扰性的方法。现在我只想知道:我只是大量地遗漏了一些东西,还是AsyncTask真的完全有缺陷?你的工作经验如何?你是怎么解决这些问题的?谢谢你的意见。
3 回答
![?](http://img1.sycdn.imooc.com/5333a0780001a6e702200220-100-100.jpg)
烙印99
TA贡献1829条经验 获得超13个赞
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(...); }}
![?](http://img1.sycdn.imooc.com/5458463b0001358f02200220-100-100.jpg)
ibeautiful
TA贡献1993条经验 获得超5个赞
原因很明显:如果活动被破坏,从而触发了任务,该怎么办?
AsyncTask
onDestroy()
AsyncTask
onCreate()
- 3 回答
- 0 关注
- 359 浏览
添加回答
举报
0/150
提交
取消