CalledFromWrongThreadException: только исходный поток, который создал иерархию представлений, может касаться представлений

у меня проблема со следующей ошибкой в Android:

CalledFromWrongThreadException;: Только исходный поток, создавший вид иерархии может коснуться его мнения

кажется, это происходит, когда я пытаюсь обновить Textview в моей деятельности, вызов для обновления TextView из моей деятельности, но я все еще получаю вышеуказанную ошибку.

у меня это так:

метод onCreate() - настройка кнопок и текста вид.

onStateChange () - прослушиватель уведомлений об изменениях состояния, когда это получает уведомление, если изменяет TextView, чтобы сказать другой текст.

когда я получаю уведомление о новом тексте, я пытаюсь изменить TextView следующим образом:

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

но я получаю вышеуказанную ошибку.

из googling, похоже, я должен использовать обработчик для изменения TextView или, возможно, использовать AsyncTask?

может ли кто-нибудь объяснить, какой из них лучше использовать и почему?

EDIT: ДОБАВЛЕНЫ ФРАГМЕНТЫ КОДА:


     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
                }});
}

5 ответов


Похоже, вы находитесь в неправильном потоке. Попробуйте использовать обработчик для обновления GUI в правом потоке. См.обработка дорогостоящих операций в потоке пользовательского интерфейса пример из android.com - ... В основном вы бы обернуть byeSetup на Runnable и вызывать его с помощью Handler экземпляра.

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

расширение ответа willcodejavaforfood для ясности и реализации...

я получил это, чтобы работать, и ниже, как я это сделал. Я запускаю несколько потоков обработки в Службе, поэтому другие решения, которые запускаются в Activity, не работают, например runOnUiThread(new Runnable() {}...

поместите это в верхней части вашего класса обслуживания, чтобы он был доступен везде в этом классе:

Handler handler;

поместите это в свой класс обслуживания onCreate метод или что-то, что загружается на Сервис основной поток

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

поместите это в свой дополнительный поток, чтобы "отправить назад" код для запуска в UI или service UI (whatevers его называют):

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

для других просто замените byeSetup (); своими инструкциями или методами кода. byeSetup () - метод выборки. Надеюсь, это сэкономит ваше время.


этот метод предназначен только для деятельность и лучше, когда изменение связано с основным потоком (UiThread). Используйте его внутри другого потока, чтобы изменить любое представление.

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

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

другой подход, на этот раз с использованием 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();