在几个活动中重用Android AsyncTask的模式?

时间:2012-06-20 07:04:39

标签: android design-patterns android-activity android-asynctask reusability

我的项目中有几个Activity子类,每个子类都调用一个基于SOAP的Web服务,处理并显示结果。 SOAP序列化,调用处理和将结果解析为各种POJO对象都封装在MyWebService类中。该类通过AsyncTask执行实际的Web服务调用。

为了能够将结果传回给调用的Activity子类,我想我强制所有这些活动都应该实现一个WebServiceResultProcessor接口,定义一个函数(processWebServiceResults)作为AsyncTask的回调,从onPostExecute调用。

我还想在Web服务调用期间显示ProgressDialog。这是我的问题。为了能够显示ProgressDialog(来自MyWebService或它的AsyncTask),我需要传递对调用者Activity的Context的引用。并且为了能够从AsyncTask执行回调函数,我需要传递相同的对象引用,但这次是作为WebServiceResultProcessor。这在我看来是一种代码气味,两次传递相同的物体,但是看不到任何方法。我可以创建一个新的基类,扩展Activity类并从扩展类强制继承,而不是接口,但这意味着我将排除ListActivity等喜欢使用此MyWebService类。

有更好的方法吗?

3 个答案:

答案 0 :(得分:4)

+1,一个很好的问题!

这不是您问题的直接答案。但是,让我说我认为AsyncTask不是这种东西的正确选择。我想是的,因为在这种情况下,AsyncTask包含对Activity(通过ProgressDialog实例或要从onPostExecute()调用的回调)的引用。

想象一下:在Android中,操作系统可能会在Activity执行其AsyncTask之前终止doInBackground()。当然,这是一种极端情况,但并非不可能。考虑一个场景:用户获得一个来电,你的活动变得不可见,操作系统需要更多的RAM,因此它决定杀死你的活动。至少是内存泄漏情况。

我不知道为什么Google会真正隐藏有关如何将UI与后台任务正确分开的信息。是的,他们说“使用服务”。但这不是一项微不足道的事。遗憾的是谷歌几乎为每个开发主题提供了很好的指南,但不是这个。不过,我可以建议查看“Google I/O 2010 - Android REST client applications”演示文稿以获取灵感。看起来他们给出了如何在Android中完成此类操作的关键。

答案 1 :(得分:3)

您可以查看此博客文章(part 1part 2),该文章使用AsyncTaskLoader实现Web服务,并使用Service组件实现相同的Web服务。此外,它显示了两种方法之间的差异,并且对文章也有一些有趣的评论。

答案 2 :(得分:0)

尽管有Arhimed的警告,我最终还是使用了AsyncTask,因为它仍然符合我的目的。我只是确保调用Web服务的所有活动在onDestroy()上向调用的AsyncTask发送cancel()。 AsyncTask实现本身通过在必要时检查isCancelled()来优雅地处理取消请求。

至于最初的问题,我一定有失误 - 解决方案非常简单。我将Activity子类实例作为Object传递给AsyncTask,并根据需要将其转换为Context或WebServiceResultProcessor。碎片显示它是如何工作的:

if (callerActivity instanceof Context) {
    ProgressDialog dialog = new ProgressDialog((Context)callerActivity);
}

...

if (callerActivity instanceof WebServiceResultProcessor) {
    ((WebServiceResultProcessor)callerActivity).processWebServiceResults(soapObject);
}