我有一个名为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)
我还考虑过尝试通过意图传递View,但不知道它是如何工作的。我需要做些什么工作?
答案 0 :(得分:25)
我遇到了类似的问题,其中需要更新来自单独线程的Web服务响应的ListView。
分析similar question& example,这是一个适合您的解决方案:
public class A extends Activity implements Callback {
callserviceB () { } // where your service B being called;
@Override
public void returnServiceResponse() {
workOnResponse();
handler.sendEmptyMessage(0);
}
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
//update your view from here only.
}
}
}
public class B implements Runnable {
Callback callback;
public void run() {
//your business logic.
callback.returnServiceResponse();
}
}
public interface Callback {
public void returnServiceResponse();
}
答案 1 :(得分:21)
您必须从GUI线程更新窗口小部件,即“创建视图层次结构的线程”。执行此操作的标准方法是通过Handler
,并且可以在ProgressDialog Example中找到如何使用处理程序的示例(展开'带有第二个线程的示例ProgressDialog')。
答案 2 :(得分:2)
您真的不想直接从服务中操作小部件。
例如,假设用户滑出G1的键盘。您的活动将被销毁并重新创建。但是,您的服务正在保持现已不存在的活动中的小部件。充其量,不会发生更新。在最坏的情况下,更新将导致崩溃,或者您的应用程序将泄漏内存,因为旧的活动不能被垃圾收集,因为您的服务仍然保留在其上。
让服务通知活动是可以的,只要你在它们之间有适当的隔离,并且活动在销毁时就会从服务中分离出来。
答案 3 :(得分:1)
另一种方法是利用 os.android.AsyncTask 进行处理。