我的项目中有几个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类。
有更好的方法吗?
答案 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 1和part 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);
}