web-dev-qa-db-ger.com

CalledFromWrongThreadException: Nur der ursprüngliche Thread, der eine Ansichtshierarchie erstellt hat, kann Ansichten berühren

Ich habe ein Problem mit dem folgenden Fehler in Android:

CalledFromWrongThreadException ;: Nur der ursprüngliche Thread, der eine .__ erstellt hat. Die Ansichtshierarchie kann ihre Ansichten berühren

Es scheint zu geschehen, wenn ich versuche, eine Textansicht in meiner Aktivität zu aktualisieren, der Aufruf zur Aktualisierung der TextView von meiner Aktivität ausgeht, aber ich bekomme immer noch den obigen Fehler.

Ich habe es so:

onCreate () - legt die Schaltflächen und die Textansicht fest.

onStateChange () - Ein Listener für Benachrichtigungen über Statusänderungen, wenn eine Benachrichtigung angezeigt wird, wenn TextView geändert wird, um anderen Text anzuzeigen.

Wenn ich über einen neuen Text informiert werde, versuche ich, die Textansicht folgendermaßen zu ändern:

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

Ich bekomme aber den obigen Fehler.

Beim Googeln scheint es, als sollte ich einen Handler verwenden, um die TextView zu ändern, oder vielleicht AsyncTask verwenden?

Könnte jemand erklären, welche besser zu verwenden ist und warum?

BEARBEITEN: ADDED CODE SNIPPETS:


     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
                }});
}
45
Donal Rafferty

Sieht aus, als ob Sie im falschen Thread sind. Verwenden Sie einen Handler, um die GUI im rechten Thread zu aktualisieren. Siehe Umgang mit teuren Vorgängen im UI-Thread Beispiel von Android.com. Grundsätzlich würden Sie byeSetup in eine Runnable einschließen und mit einer Handler-Instanz aufrufen.

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

Erweiterung der Antwort von willcodejavaforfood für Klarheit und Implementierung ...

Ich habe das zum Laufen gebracht und unten habe ich es gemacht. Ich führe mehrere Verarbeitungsthreads in einem Service aus, sodass andere Lösungen, die in Activity ausgeführt werden, nicht funktionieren, wie runOnUiThread (new Runnable () {} ...).

Stellen Sie dies an die Spitze Ihrer Serviceklasse, damit Sie in dieser Klasse überall verfügbar ist:

Handler handler;

Fügen Sie dies in Ihre Serviceklasse onCreate-Methode ein oder etwas, das im Service-Haupt-Thread geladen wird

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

Fügen Sie diesen Code in Ihren zusätzlichen Thread ein, um den Code "zurückzuschicken", damit er in der Benutzeroberfläche oder in der Service-Benutzeroberfläche ausgeführt werden kann.

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

Für andere ersetzen Sie einfach byeSetup (); mit Ihren Code-Anweisungen oder Methoden. byeSetup () ist eine Beispielmethode. Ich hoffe, es wird etwas Zeit sparen. 

2
Joseph Selvaraj

Diese Methode ist nur für Activities und ist besser, wenn die Änderung am Haupt-Thread ( UiThread ) erfolgt. Verwenden Sie es in einem anderen Thread, um die Ansicht zu ändern.

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

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

Ein weiterer Ansatz, bei dem Android.os.Message verwendet wird

Haben Sie Android.os.Handler als Feld in Ihrer Aktivität definiert:

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

Dann füttere es aus deinem anderen Thread wie folgt:

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

Sie können die eingebaute Post-Methode von view verwenden, um den Inhalt in einem anderen Thread zu aktualisieren, z.

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