如何从生成的后台服务访问原始活动的视图
我有一个名为 A 的活动,在选择菜单项 0 时,它会生成服务 B,该服务在新线程中启动可运行的 C。 我在活动 A 中有一个 TextView,我想在线程 C 中访问它。
我尝试将 TextView 设为公共静态字段,但这会生成以下错误:
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.view.ViewRoot.checkThread(ViewRoot.java:2440)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.view.ViewRoot.invalidateChild(ViewRoot.java:522)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:540)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.view.ViewGroup.invalidateChild(ViewGroup.java:2332)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.view.View.invalidate(View.java:4437)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.widget.TextView.updateAfterEdit(TextView.java:4593)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.widget.TextView.handleTextChanged(TextView.java:5932)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.widget.TextView$ChangeWatcher.onTextChanged(TextView.java:6081)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.text.SpannableStringBuilder.sendTextChange(SpannableStringBuilder.java:889)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.text.SpannableStringBuilder.change(SpannableStringBuilder.java:352)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.text.SpannableStringBuilder.change(SpannableStringBuilder.java:269)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:432)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.text.SpannableStringBuilder.append(SpannableStringBuilder.java:259)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.text.SpannableStringBuilder.append(SpannableStringBuilder.java:28)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.widget.TextView.append(TextView.java:2191)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.widget.TextView.append(TextView.java:2178)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at com.android.peekaboo.DoScan$scanBody.run(DoScan.java:36)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at java.lang.Thread.run(Thread.java:1058)
我还考虑过尝试通过意图传递视图,但是不知道那会如何运作。 我需要什么才能使这项工作成功?
I have an activity called A, and on the selection of menu item 0, it spawns service B, which starts a runnable C in a new thread. I have a TextView in activity A, which I want to access in thread C.
I've tried making the TextView a public static field, but that generates the following error:
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.view.ViewRoot.checkThread(ViewRoot.java:2440)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.view.ViewRoot.invalidateChild(ViewRoot.java:522)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:540)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.view.ViewGroup.invalidateChild(ViewGroup.java:2332)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.view.View.invalidate(View.java:4437)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.widget.TextView.updateAfterEdit(TextView.java:4593)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.widget.TextView.handleTextChanged(TextView.java:5932)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.widget.TextView$ChangeWatcher.onTextChanged(TextView.java:6081)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.text.SpannableStringBuilder.sendTextChange(SpannableStringBuilder.java:889)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.text.SpannableStringBuilder.change(SpannableStringBuilder.java:352)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.text.SpannableStringBuilder.change(SpannableStringBuilder.java:269)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:432)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.text.SpannableStringBuilder.append(SpannableStringBuilder.java:259)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.text.SpannableStringBuilder.append(SpannableStringBuilder.java:28)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.widget.TextView.append(TextView.java:2191)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.widget.TextView.append(TextView.java:2178)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at com.android.peekaboo.DoScan$scanBody.run(DoScan.java:36)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at java.lang.Thread.run(Thread.java:1058)
I have also considered trying to pass the View through an intent, but do not know how that would work. What do I need to make this work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
另一种方法是利用 os.android.AsyncTask 进行处理。
The other way is to utilize os.android.AsyncTask for processing.
您确实不想直接从服务中操作小部件。
例如,假设用户滑出 G1 的键盘。 您的活动被销毁并重新创建。 然而,您的服务保留了现已失效的活动中的小部件。 充其量,更新不会发生。 在最坏的情况下,更新将导致崩溃,或者您的应用程序将泄漏内存,因为旧活动无法被垃圾收集,因为您的服务仍然保留它。
让服务通知活动是可以的,只要它们之间有适当的隔离,并且活动在被销毁时将其自身与服务分离。
You really do not want to be directly manipulating widgets from a service.
For example, suppose the user slides out the keyboard of her G1. Your activity is destroyed and recreated. Your service, however, is holding onto widgets from a now-defunct activity. At best, the updates will not occur. At worst, the updates will cause a crash, or your application will leak memory because the old activity cannot be garbage-collected, because your service still holds onto it.
Having services notify activities is OK, so long as you have decent isolation between them and the activity detaches itself from the service when it is destroyed.
您必须从 GUI 线程(也称为“创建视图层次结构的线程”)更新小部件。 标准方法是通过
Handler
s 以及如何使用处理程序的示例可以在 中找到ProgressDialog 示例(展开“带有第二个线程的 ProgressDialog 示例”)。You have to update widgets from the GUI thread, aka 'the thread that created the view hierarchy'. The standard way to do this is via
Handler
s and an example of how to use handlers can be found in the ProgressDialog Example (expand 'Example ProgressDialog with a second thread').我遇到了类似的问题,需要根据来自单独线程的 Web 服务响应更新 ListView。
在分析类似问题之后 示例,这是一个适合您的解决方案:
I was having a similar issue where a ListView was required to be updated on the web-service response coming from a separate thread.
After analyzing a similar question & example, here is a solution which should work for you: