web-dev-qa-db-ja.com

CalledFromWrongThreadException:ビュー階層を作成した元のスレッドのみがビューに触れることができます

Androidで次のエラーが発生します。

CalledFromWrongThreadException ;:ビュー階層を作成した元のスレッドのみがそのビューに触れることができます

アクティビティでTextviewを更新しようとすると発生するようです。TextViewを更新するための呼び出しはアクティビティ内からですが、上記のエラーが発生します。

私はこれを次のように持っています:

onCreate()-ボタンとテキストビューを設定します。

onStateChange()-状態の変化に関する通知のリスナー。これは、TextViewを変更して異なるテキストを言う場合に通知を取得します。

新しいテキストの通知を受け取ったら、TextViewを次のように変更しようとします。

((TextView)findViewById(R.id.title)).setText("Some Text");

しかし、上記のエラーが発生します。

グーグルから、ハンドラを使用してTextViewを変更するか、AsyncTaskを使用する必要がありますか?

誰が使用する方が良いか、そしてその理由を説明できますか?

編集:コードスニペットの追加:


     public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);  

            setContentView(R.layout.my);

            getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.my_title);  

            ((TextView)findViewById(R.id.time)).setText("Hello Text");


            findViewById(R.id.keyboardimage).setOnClickListener(new OnClickListener() {
                public void onClick(View v) {

                    Intent dialIntent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:"));
                    startActivity(dialIntent);

                        dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN,KeyEvent.FLAG_SOFT_KEYBOARD));
                        dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK));       
                }
        });

     }

//CallBacks from running Service

private final ICallDialogActivity.Stub iCallDialogActivity = new ICallDialogActivity.Stub(){

@Override
public void onStateChanged(int callState)
                throws RemoteException {    
            switch(callState){
            case GlobalData.CALL_STATUS_IDLE:

                break;

            case GlobalData.CALL_STATUS_DISCONNECTING:
                byeSetup();
                break;
    } 

};

public void byeSetup(){

            ((TextView)findViewById(R.id.time)).setText("Bye Text");

            findViewById(R.id.keyboardimage).setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    //Void the Button
                }});
}
47
Donal Rafferty

間違ったスレッドにいるように見えます。ハンドラーを使用して、正しいスレッドでGUIを更新してみてください。 Android.comの UIスレッドでの高価な操作の処理 の例を参照してください。基本的に、byeSetupRunnableをラップし、Handlerインスタンスで呼び出します。

Handler refresh = new Handler(Looper.getMainLooper());
refresh.post(new Runnable() {
    public void run()
    {
        byeSetup();
    }
});
75

Willcodejavaforfoodの答えを明確にして実装するために拡大しています...

これが機能するようになりました。以下にその方法を示します。サービスで複数の処理スレッドを実行しているため、runOnUiThread(new Runnable(){} ...など、Activityで実行される他のソリューションは機能しません。

これをサービスクラスの先頭に配置して、このクラスのどこからでもアクセスできるようにします。

Handler handler;

これをサービスクラスのonCreateメソッドまたはServiceメインスレッドでロードするものに入れます

handler= new Handler(Looper.getMainLooper());

これを追加のスレッド内に配置して、コードを「ポストバック」し、UIまたはサービスUI(と呼ばれるもの)で実行します。

handler.post(new Runnable() {
    public void run() {
        playNext(); //or whatever method you want to call thats currently not working
    }
});
3
Kevin

変更がメインスレッドに関係する場合(iThread)。ビューを変更するには、別のスレッド内で使用します。

runOnUiThread(new Runnable() {
    @Override
    public void run() {

      // TODO your Code 
        et_Pass.setText("");
    }
});
3
Keshav Gera

その他の場合は、byeSetup()を置き換えるだけです。コードステートメントまたはメソッドを使用します。 byeSetup()はサンプルメソッドです。時間の節約になることを願っています。

2
Joseph Selvaraj

別のアプローチ、今度はAndroid.os.Message

持ってる Android.os.Handlerアクティビティ内のフィールドとして定義:

private final Handler myTextHandler = new Handler(new Handler.Callback() {
    @Override
    public boolean handleMessage(Message stringMessage) {
        textView.append((String) stringMessage.obj);
        return true;
    }
});

次に、他のスレッドから次のようにフィードします。

Message stringMessage = Message.obtain(myTextHandler);
stringMessage.obj = "Hello!";
stringMessage.sendToTarget();
0

ビューの組み込みのpostメソッドを使用して、kotlinで編集テキストを使用しているように、他のスレッドのコンテンツを更新できます。

address_box.post { address_box.text="my text"}
0
Nero