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)
ビューをインテントに通すことも検討しましたが、それがどのように機能するかわかりません。これを機能させるには何が必要ですか?
GUIスレッド(別名「ビュー階層を作成したスレッド」)からウィジェットを更新する必要があります。これを行う標準的な方法は Handler
sで、ハンドラーの使用例は ProgressDialog Example (expand 'Example ProgressDialog with 2番目のスレッド ')。
別のスレッドからのWebサービス応答でListViewを更新する必要があるという同様の問題がありました。
同様の質問 & 例 を分析した後、これがあなたのために働くはずの解決策です:
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();
}
サービスからウィジェットを直接操作したくない場合。
たとえば、ユーザーが彼女のG1のキーボードを引き出したとします。アクティビティが破棄され、再作成されます。ただし、あなたのサービスは、今はなくなった活動からのウィジェットを保持しています。せいぜい、更新は行われません。最悪の場合、更新によりクラッシュが発生するか、サービスが保持しているために古いアクティビティをガベージコレクションできないため、アプリケーションがメモリリークを起こします。
サービスがアクティビティに通知するようにしても、アクティビティが適切に分離されていて、アクティビティが破棄されるとアクティビティからサービスから切り離されます。
もう1つの方法は、処理にos.Android.AsyncTaskを利用することです。