CalledFromWrongThreadException在Onclick方法内部发送消息使用Handler到其他线程

时间:2013-12-06 07:19:48

标签: android multithreading actionlistener

获取CalledFromWrongThreadException,只有创建视图层次结构的原始线程才能触及其视图。

在行handler2.sendMessage(msg);上,用于从UI线程向下面的MulitThreaderSendback类发送短文本消息。

调用sendMessage(msg)在从onCreate方法内部调用它时可以正常工作,但是当我把它放在onClick侦听器中时,它会导致此异常崩溃。

如何避免此崩溃并能够从onclick侦听器调用它,以便我可以使用按钮按下来发送消息?

FROM LOGCAT:

E/AndroidRuntime(14366): FATAL EXCEPTION: Thread-1433
E/AndroidRuntime(14366): android.view.ViewRootImpl$CalledFromWrongThreadException:
Only the original thread that created a view hierarchy can touch its views.
E/AndroidRuntime(14366): android.view.ViewRootImpl.checkThread(ViewRootImpl.java:5432)
E/AndroidRuntime(14366): android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:970)

代码是:

public class MainActivity extends Activity implements Runnable {

TextView textViewOne;
TextView textViewTwo;
TextView textViewThree;
TextView textViewFour;
TextView textViewFive;
RelativeLayout relativeLayoutOne;
Handler handler;
Handler handler2;
Message msg;
Context context;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    context = this;

    relativeLayoutOne = (RelativeLayout) findViewById(R.id.relativeLayout1);
    textViewOne = (TextView) findViewById(R.id.textView1);
    textViewTwo = (TextView) findViewById(R.id.textView2);
    textViewThree = (TextView) findViewById(R.id.textView3);
    textViewFour = (TextView) findViewById(R.id.textView4);
    textViewFour = (TextView) findViewById(R.id.textView5);

    handler = new Handler();

    // starting this class that implements Runnable
    this.run();

    // starting class that extends Thread
    MultiThreader multiThreader = new MultiThreader(handler);
    multiThreader.start();

    // starting class that implements Runnable
    MultiThreader2 multiThreader2 = new MultiThreader2(handler);
    Thread thread = new Thread(multiThreader2);
    thread.start();

    MulitThreaderSendback multiSendBack = new MulitThreaderSendback();
    Thread thread2 = new Thread(multiSendBack);
    thread2.start();

    synchronized (multiSendBack) {
    while (handler2 == null) {
        try {
           multiSendBack.wait();
        } catch (InterruptedException e) {
            //Ignore and try again.
        }
    }
    }

    Bundle bundle = new Bundle();
    String messageToSend = "message from UI class";
    bundle.putString("message", messageToSend);
    Random random = new Random();
       int messageText = random.nextInt(30);
       String putIt = String.valueOf(messageText);
       bundle.putString("message", putIt);
          msg = Message.obtain();
                msg.setData(bundle);

 //  handler2.sendMessage(msg); // <-- WORKS OK HERE, NO CRASH

    relativeLayoutOne.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            handler2.sendMessage(msg);  // <-- FATAL ERROR:  CalledFromWrongThreadException
        }

    });


    } // end oncreate


public void setTextViewThree(String textToSet) {
    textViewFour.setText(textToSet);

}

public void setTextViewFour(String textToSet) {
    textViewFive.setText(textToSet);

}

// local class runnable
@Override
public void run() {

    textViewOne.setText("message from local class runnable");

}

// multiThreader inner class
class MultiThreader extends Thread {
    Handler handler;

    public MultiThreader(Handler handler) {
        this.handler = handler;

    }

       @Override
       public void run() {
            handler.post(new Runnable() {
                 @Override
                 public void run() {
                     textViewTwo.setText("message from multithreader class");
                 } // end inner run
            });

          } // end outer run

    } // end MultiThreader inner class

// external multiThreader2 inner class
class MultiThreader2 implements Runnable {
     Handler handler;

    public MultiThreader2(Handler handler) {
        this.handler = handler;
    }

       public void run() {

            handler.post(new Runnable() {
                 @Override
                 public void run() {
            textViewThree.setText("message from MultiThreader2 class");
                 } // end inner run
            });

       } // end outer run


 } // end MultiThreader2 inner class

class MulitThreaderSendback implements Runnable {

    int x = 0;

    @Override
    public void run() {
        // TODO Auto-generated method stub

         Looper.prepare();

         synchronized(this) {

         handler2 = new Handler() {
             public void handleMessage(Message msg) {
                 Bundle bundle =  msg.getData();
                 String receivedString = bundle.getString("message");

              setTextViewThree("string received from UI thread: " + receivedString);



             }
         };
         notifyAll();
         }

     Looper.loop();

    } // end run method

} // end MultiThreaderSendback inner class

 } // end outer class mainactivity

1 个答案:

答案 0 :(得分:1)

您可以在此方法中嵌入行handler2.sendMessage(msg);

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

}

});

试试这个