CalledFromWrongThreadException: только исходный поток, создавший иерархию представлений, может касаться представлений - PullRequest
47 голосов
/ 19 июля 2010

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

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

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

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

OnCreate () -установка кнопок и текстового представления.

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

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

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

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

После поиска в Google, мне кажется, что я должен использовать обработчик для изменения 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 }}); }

Ответы [ 6 ]

74 голосов
/ 19 июля 2010

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

Handler refresh = new Handler(Looper.getMainLooper());
refresh.post(new Runnable() {
    public void run()
    {
        byeSetup();
    }
});
3 голосов
/ 07 января 2015

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

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

. Поместите это в начало класса обслуживания,это доступно везде в этом классе:

Handler handler;

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

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

Поместите это в ваш дополнительный поток, чтобы 'postback 'код для запуска в пользовательском интерфейсе или пользовательском интерфейсе службы (в зависимости от того, как он вызывается):

handler.post(new Runnable() {
    public void run() {
        playNext(); //or whatever method you want to call thats currently not working
    }
});
2 голосов
/ 13 ноября 2017

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

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

      // TODO your Code 
        et_Pass.setText("");
    }
});
2 голосов
/ 26 мая 2012

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

0 голосов
/ 01 ноября 2018

Вы можете использовать встроенный метод представления view для обновления содержимого в другой теме, как если бы я использовал редактирование текста в kotlin.

address_box.post { address_box.text="my text"}
0 голосов
/ 28 марта 2017

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