5

我的项目中有几个 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 类。

有一个更好的方法吗?

4

3 回答 3

4

+1,一个很好的问题!

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

试想一下:在 Android 中,操作系统可能会ActivityAsyncTask执行其doInBackground(). 当然,这是某种极端情况,但这并非不可能。考虑一个场景:用户接到来电,您的活动变得不可见,操作系统需要更多 RAM,因此它决定终止您的活动。至少是一个内存泄漏案例。

我不知道为什么 Google 从字面上隐藏了有关如何将 UI 与后台任务正确分离的信息。是的,他们说“使用服务”。但这不是一项微不足道的工作。遗憾的是,谷歌几乎为每个开发主题都提供了很好的指南,但没有在这个主题上提供。尽管如此,我还是建议您查看“ Google I/O 2010 - Android REST 客户端应用程序”演示文稿以获得灵感。看起来他们给出了如何在 Android 中完成这些事情的关键。

于 2012-06-20T07:36:06.257 回答
3

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

于 2012-06-20T07:57:01.873 回答
0

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

至于最初的问题,我一定是有失误——解决方案真的很简单。我将 Activity 子类实例作为对象传递给 AsyncTask,并根据需要将其转换为 Context 或 WebServiceResultProcessor。显示其工作原理的片段:

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

...

if (callerActivity instanceof WebServiceResultProcessor) {
    ((WebServiceResultProcessor)callerActivity).processWebServiceResults(soapObject);
}
于 2012-06-21T23:59:54.270 回答