我正在尝试在远程服务中创建包含内容观察者但仍然收到错误的应用程序:
“无法在未调用Looper prepare的线程内创建处理程序”
我已经在Android开发者网站上做了很多阅读以及许多谷歌搜索我还没有完全理解这个问题。到目前为止我从中获取的是内容观察者需要一个线程来运行(对于Handler)。添加后:
Looper.myLooper().prepare();
mObserver = new Observer(new Handler());
在创建新的内容观察器之前立即调用Looper使应用程序正常工作。但是我想更好地理解为什么会这样 - 我在网上找到的任何东西都没有帮助我理解为什么到目前为止。另外,添加Looper代码行是否正确有效?我是否需要进行任何清理以防止内存泄漏?
解释越简单越好。仍然在我的Android开发的第一个月并取得了良好的进展 - StackOverflow一直是一个巨大的帮助!感谢。
更新
在玩完并阅读更多内容后,我认为可以更好地掌握如何完成这项工作以及如何清理它,但仍然缺少一小部分。
从我收集的内容中,我可以将Looper.prepare()称为静态方法。然后,我可以使用新的Handler()创建我的内容观察器。当我想要停止这个内容观察者时,我可以使用mLooper = Looper.myLooper.getThread()获取对象的线程,然后我可以运行mLooper.quit()。但是,我必须和我什么时候打电话,为什么我会打电话给mLooper.loop()?
更新2
好的,这就是我要解决的问题。该应用程序在内部,解释有点复杂,但这是我最好的镜头:
我们正在运行一个接收和发送网络数据的远程服务。我们的消息类型在数据中定义,因此我们可以将它们引导到手机上的正确数据库。有一个Jar接口文件供其他APK导入以连接到正在运行的服务。当收到他们感兴趣的新消息时,这些APK可以注册接收广播。为此,内容观察者在APK使用的内容uri中注册,因此当新数据被添加到数据库时,内容观察者将发送广播以警告正确的APK。然后,APK可以按照自己的意愿处理。
因此可以使用null作为新内容观察器的参数,或者使用新的Handler()为此观察者创建线程会更好。
我试过创建一个线程,但到目前为止它没有用,我想是因为我还没有启动Looper.loop(这冻结了我的服务)。任何建议将不胜感激!提前致谢。
答案 0 :(得分:3)
当你在一个线程中启动Looper时,其他线程可以向它发送消息,它将接收并处理它们。此方案在Android中广泛使用:looper在UI线程上初始化,并且其他线程被分配以执行一些lenghty操作。那些“工人”线程可以通过向其发送消息Handler
将其辛苦劳动的结果发送到UI线程。
而且,是的,你需要调用Looper.loop()
才能让事情运转起来。否则你的处理程序永远不会收到任何事件而且您似乎必须调用Looper.quit()
才能阻止它并避免资源泄漏。
这是有趣的部分。从ContentObserver's source code来看,它并不完全需要Handler。如果您传递null
,它只会在运行它的同一个线程上执行onChange()
。
P.S。我的开发机器坏了,所以我无法验证我的陈述。也许当前版本的ContentObserver确实需要Handler才能工作。实验将显示。