2011-07-13 24 views
1

我正在写一个应用程序中有一个很奇怪的问题。这可能很简单,我误解了有关服务,AsyncTasks以及何时再次访问UI线程的内容。服务,AsyncTasks和CalledFromWrongThreadException

该应用程序由一个主要活动组成,通过它您可以导航到多个其他活动。该应用程序有两个服务,一个位于后台,在应用程序处于前台时定期轮询,另一个运行“AACPlayer”以流式传输实时广播流。

其中一项活动是为无线电设备提供UI控件的活动之一,为无线电设备启动服务。要做到这一点,一个AsyncTask被激发来获取和分析PLS文件,最后用流的正确URL来启动服务。启动服务也启动AACPlayer。一旦数据流开始播放,就会发出广播,表示数据流已开始播放。持有无线电控件的活动中的广播接收器处理意图并更新UI。

这项工作很好,除了一种竞争条件,通过看似随意的组合离开应用程序或退出无线电屏幕,在服务已经广播其意图更新UI之前,所有其他活动现在似乎在外面运行的UI线程。在此情况下触发的其他任何活动都会收到一个异常,表明它处于非法状态,并且无法修改任何与UI相关的任何操作,因为我们没有在UI线程上运行。通常的罪魁祸首是:W/System.err(3818): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

有没有其他人遇到过,突然间整个应用程序不再运行在其通常的UI线程上,并且所有其他活动都报告此异常?我认为我没有任何代码可以做任何会导致此错误的非法行为。 AsyncTasks中没有UI相关的东西。由广播接收器(从无线电服务接收)触发的回调确实触及UI,但我想不出用不同的方式来做到这一点?

即使应用程序强制自行退出,该问题仍未修复,但在应用程序强制退出或从Android设置清除其数据时得到补救。

编辑 - 由于这里要求的一些代码,列出正在启动的服务和启动服务活动/控制UI:https://gist.github.com/1080797

任何想法,将不胜感激。谢谢。

+0

请添加一些代码... – Marmoy

+0

创建一个服务文件和该服务的“主管”活动的要点。 https://gist.github.com/1080797 – jlindenbaum

回答

1

尝试将您的PlayerServiceUpdateReceiver的初始化移动到onCreate()。我不认为你需要在每个onResume()重新初始化它,你只需要重新注册它。你懂我的意思吗?

我认为正在发生的事情是您正在接收器的回调函数被新实例覆盖。

或者我可能是完全错误的,这是正确的做法。如我错了请纠正我。

+0

初始化现在在onCreate,注册仍然在onResume - 是你的意思? https://gist.github.com/1080797/c473eb5084f53fc22c3a8b25cd136dede9958e0a – jlindenbaum

+0

是的,这是否有所作为? – Marmoy

+0

只是被放到要测试的设备上。很难说它是否修复了它,或者我们无法重现它。 ;) 你有没有看到有什么你会做不同/更好? – jlindenbaum