【问题标题】:IntentService getting wedgedIntentService 陷入困境
【发布时间】:2010-10-06 18:47:30
【问题描述】:

我已经构建了一个应用程序,它使用 IntentService 来操作应用程序的数据库和调用 Web 服务。

例子:

我有一个 Activity,它是一个项目列表。此列表由 CursorAdapter 填充。每个项目都有一个复选框,列表按选中排序(未选中的项目在顶部,选中的项目在底部)。当一个项目的复选框被选中时,我向我的 IntentService 发送一个 Intent,告诉它在数据库表中为该项目标记选中的列,然后广播一条消息,Activity 看到它并重新查询光标。

当我使用移动设备并开始快速检查复选框时,应用程序基本上会挂起。 UI 不会挂起,但后台的 IntentService 会挂起。我可以判断,因为屏幕上的光标没有刷新。

据我了解,传递给 IntentServices 的 Intent 不会被异步处理。那是对的吗?它的行为几乎就像我需要使用信号量一样,但我不明白为什么要单独排队和处理 Intent。

假设我选中了 3 个复选框;所以有3个意图排队。在第一个之后,我广播了一条消息,Activity 收到了这条消息,告诉它重新查询它的光标。可能是因为我在处理第二个意图(更新表中的另一行)的同时重新查询游标吗?查询游标发生在 UI 线程上。

^ 我认为这是我的问题。我应该用什么来同步这个?信号量?有人可以指点我一些文档/示例吗?

另一个潜在的问题是,如果我的 Activity 管理桌子上的光标;我的 IntentService 也从同一个表中查询游标。我有发生这种情况的实例,因为我的 IntentService 正在遍历光标中的每一行以查找要发送到 Web 服务的项目。尽管只要光标不同时查询,我认为这不会是一个问题?

还有人有其他想法吗?

【问题讨论】:

  • 一些快速的想法:我会在系统的每个部分添加日志记录,以真正找到卡纸的位置。数据库访问层是 ContentProvider(它们不是为多线程设计的)吗?另外,为什么要在 Activity 中使用 Handler 时使用 IntentService 呢?同样,如果 Activity 在主线程上查询数据库,为什么还要担心异步发布更新,而不是(比如说)AsyncQueryHandler?
  • 是的,我的数据库访问是通过 ContentProvider 进行的。我将研究 AsyncQueryHandler

标签: android service android-intent


【解决方案1】:

当一个项目的复选框被选中时,我向我的 IntentService 发送一个 Intent,告诉它在数据库表中为该项目标记选中的列,然后广播一条消息,Activity 看到它并重新查询光标。

这有一种“用别克打苍蝇”的感觉。

据我了解,传递给 IntentServices 的 Intent 不会被异步处理。对吗?

IntentService 中的onHandleIntent() 在后台线程上调用,而startService() 始终是异步的。

它的行为几乎就像我需要使用信号量一样,但我不明白为什么要单独排队和处理 Intent。

单个IntentsIntentService 排队并按顺序处理。

可能是因为我在处理第二个 Intent(更新表中的另一行)的同时重新查询光标吗?

这当然没有帮助。

我应该使用什么来同步它?信号量?

我只使用synchronized(someStaticDataMember),但信号量应该可以工作。

虽然我不认为这会是一个问题,只要光标不同时查询?

直到Cursor 被触摸(例如,moveToFirst()getCount())才会执行实际查询。之后,只要查询结果集小于1MB,结果全部在Cursor中。

我部分同意 Christopher 的观点:使用一些日志记录来确定到底发生了什么,并考虑使这更轻量级(例如,用于数据库写入的 AsyncTask 而不是 IntentService)。

【讨论】:

  • 如果我生成了一个线程来写入数据库,但在线程完成之前 Activity 被回收了怎么办?我知道这种可能性很小,因为写作是一种快速的操作,但是说我正在写一个对象数组。该数据与 Activity 相关联,如果 Activity 被回收,我的线程就有麻烦了。你能指出一个同步静态成员的例子吗?我已经在单例构造函数上做到了这一点,但我不太确定如何将它包装在两个单独的代码块中。
  • 我还应该注意,由于我观看了视频,我的数据库插入/更新/删除位于 IntentService 中。有一个 Google I/O 2010 演示视频,其中一位 Google 工程师讨论了构建 Web 服务繁重应用程序的模型。他断言,包括数据库调用在内的长时间运行的操作应该发生在服务中。
  • @Andrew:“如果 Activity 被回收,我的线程就有问题了”——为什么? AsyncTask 将运行完成。 “你能给我举一个同步静态成员的例子吗?” -- 不是真的,它是微不足道的 Java。如果您有能力编写IntentService,使用synchronized() 关键字应该是在公园散步! “他断言长期运行的操作,包括数据库调用,应该发生在服务中。” - 我在那里。 IntentService 不是在主应用程序线程之外工作的唯一模式,而且我和 Google 员工在某些事情上存在分歧。
  • @Andrew:我并不是说你必须放弃使用IntentService,只是我不会将IntentService 用于像简单的数据库操作这样微不足道的事情。跨度>
  • 假设我有属于 Activity 的成员变量,它存储一些数据。我想将这些片段写入数据库。我启动了一个 asynctask 来编写它们,并且在 asynctask 执行时,Activity 被系统回收或销毁(屏幕旋转)。这不会造成问题吗?
猜你喜欢
  • 2013-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-05
相关资源
最近更新 更多