3

我正在尝试在远程服务中创建一个包含 Content Observers 的应用程序,但不断收到错误消息:

“无法在未调用 Looper 准备的线程内创建处理程序”

我在 Android 开发者网站上做了很多阅读以及许多谷歌搜索,但我仍然没有完全理解这个问题。到目前为止,我从中得到的是 Content Observer 需要一个线程来运行(对于 Handler)。添加后:

Looper.myLooper().prepare();
mObserver = new Observer(new Handler());

在创建新的 Content Observer 之前立即调用 Looper 可使应用程序正常工作。但是,我想更好地理解为什么会这样——到目前为止,我在网上找不到任何东西可以帮助我理解为什么。此外,添加 Looper 代码行是正确且有效的做法吗?我需要对此进行任何清理以防止以后发生内存泄漏吗?

解释越简单越好。仍然在我进行 Android 开发的第一个月并取得了不错的进展 - StackOverflow 提供了巨大的帮助!谢谢。

更新
在玩耍并阅读更多内容之后,我认为对如何完成这项工作以及如何清理它有了更好的了解,但仍然缺少一小部分。

根据我收集到的信息,我可以将 Looper.prepare() 称为静态方法。然后我可以使用新的 Handler() 创建我的 Content Observer。当我想停止这个 Content Observer 时,我可以使用 mLooper = Looper.myLooper.getThread() 获取对象的线程,然后我可以运行 mLooper.quit()。但是我必须,什么时候,我为什么要调用 mLooper.loop()?

更新 2
好的,这里是我要解决的问题。该应用程序在内部,解释起来有点复杂,但这是我最好的选择:

我们有一个远程服务正在运行,它接收和发送网络数据。我们的消息类型是在数据中定义的,因此我们可以将它们定向到手机上的正确数据库。有一个 Jar 接口文件供其他 APK 导入以连接到正在运行的服务。当收到他们感兴趣的新消息时,这些 APK 可以注册以接收广播。为此,内容观察者注册了 APK 使用的内容 uri,因此当新数据添加到数据库时,内容观察者将发送广播以提醒正确的 APK。然后 APK 可以随心所欲地处理这个问题。

那么是否可以使用 null 作为新内容观察者的参数,还是使用 new Handler() 为该观察者创建线程更好。

我尝试创建一个线程,但到目前为止它不起作用,我认为这是因为我还没有启动 Looper.loop(这会冻结我的服务)。任何建议将不胜感激!提前致谢。

4

1 回答 1

3

当你在一个线程中启动 Looper 时,其他线程获得了向它发送消息的能力,它会接收和处理它们。这种方案在 Android 中被广泛使用:looper 在 UI 线程上初始化,其他线程被分配执行一些冗长的操作。那些“工人”线程可以通过向 UI 线程发布消息来将他们辛勤劳动的结果发送到 UI 线程Handler

而且,是的,你需要打电话Looper.loop()才能让事情顺利进行。否则,您的处理程序将永远不会收到任何事件。似乎您必须调用Looper.quit()才能停止它并避免泄漏资源。

这是有趣的部分。从ContentObserver 的源代码来看,它并不完全需要 Handler。如果你通过null,它只会onChange()在它运行的同一个线程上执行。

PS 我的开发机器停机了,所以我无法验证我的陈述。也许当前版本的 ContentObserver 确实需要 Handler 才能工作。实验会证明。

于 2011-10-06T15:48:32.757 回答