2010-07-19 3 views
43

У меня есть проблема со следующей ошибкой в ​​Android:CalledFromWrongThreadException: только исходный поток, который создал вид иерархия может коснуться взглядами

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

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

Я его так:

OnCreate() -множествах до кнопок и вид текста.

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

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

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

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

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

Вы находитесь в подклассе? onStateChange переопределяется где? – Pentium10

+0

Hi Pentium10, он переопределяется через интерфейс AIDL и обменивается данными с Сервисом, Служба получит уведомление об изменении, а затем сообщит Activity для обновления своего TextView на основе этого. Я добавил фрагменты кода, чтобы лучше продемонстрировать, что я пытаюсь. Ошибка кажется очень случайной и появляется, когда активность находится на переднем плане и не работает. –

+1

Возможный дубликат [CalledFromWrongThreadException] (http://stackoverflow.com/questions/3413544/calledfromwrongthreadexception) – jww

ответ

69

Посмотрите, как вы на ложном потоке. Попробуйте использовать Handler для обновления графического интерфейса в правой ветке. См. Пример Handling Expensive Operations in the UI Thread с сайта android.com. В основном вы обертываете byeSetup в Runnable и вызывают его с помощью экземпляра Handler.

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

Похоже, мне не нужно убивать меня. * Уф * –

2

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

3

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

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

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

Handler handler; 

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

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

Поместите это внутри вашей дополнительной нити на код «назад», чтобы получить доступ к пользовательскому интерфейсу или пользовательскому интерфейсу службы:

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

Другой подход, на этот раз делает использование 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(); 
1
     runOnUiThread(new Runnable() { 
          @Override 
          public void run() { 

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