Android笔记(三十二) Android中线程之间的通信(四)主线程给子线程发送消息

         之前的例子都是我们在子线程(WorkerThread)当中处理并发送消息,然后在主线程(UI线程)中获取消息并修改UI,那么可以不可以在由主线程发送消息,子线程接收呢?我们按照之前的思路写一下代码:

package cn.lixyz.handlertest;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;


public class MainActivity extends Activity {

    private Button button;
    private Handler handler;
    private int i = 0;


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

        button = (Button) findViewById(R.id.button);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("TTTT", "onClick:" + Thread.currentThread().getName());
                Message msg = handler.obtainMessage();
                handler.sendMessage(msg);
            }
        });

        WorkerThread wt = new WorkerThread();
        wt.start();
    }


    class WorkerThread extends Thread {
        @Override
        public void run() {
            super.run();
            handler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    Log.d("TTTT", "收到了消息对象");
                }
            };
        }
    }
}
MainActivity.java
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="30dp"
        android:text="Send Message" />

</LinearLayout>
activity_main.xml

         上面的问题貌似没什么错误,但运行时却出错

         抛出异常:

09-17 04:01:31.655  15854-15869/? E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-120
    Process: cn.lixyz.handlertest, PID: 15854
    java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
            at android.os.Handler.<init>(Handler.java:200)
            at android.os.Handler.<init>(Handler.java:114)
            at cn.lixyz.handlertest.MainActivity$WorkerThread$1.<init>(MainActivity.java:48)
            at cn.lixyz.handlertest.MainActivity$WorkerThread.run(MainActivity.java:48)

  

         提示我们没有调用Looper.prepare(),无法创建线程,原因是非主线程中默认是没有创建Looper对象的,需要先调用Looper.prepare()启用Looper。修改一下上面的代码。

package cn.lixyz.handlertest;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;


public class MainActivity extends Activity {

    private Button button;
    private Handler handler;


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

        button = (Button) findViewById(R.id.button);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Message msg = handler.obtainMessage();
                msg.what = 100;
                handler.sendMessage(msg);
                Log.d("TTTT", "sendMessage:" + Thread.currentThread().getName());
            }
        });

        WorkerThread wt = new WorkerThread();
        wt.start();
    }


    class WorkerThread extends Thread {
        @Override
        public void run() {
            super.run();
            Looper.prepare();
            handler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    Log.d("TTTT", "handleMessage:" + Thread.currentThread().getName());
                    int i = msg.what;
                    Log.d("TTTT", "收到了消息对象:" + i);
                }
            };
            Looper.loop();
        }
    }
}
MainActivity.java
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="30dp"
        android:text="Send Message" />

</LinearLayout>
activity_main.xml

         运行结果:

09-17 04:29:48.669  28397-28397/cn.lixyz.handlertest D/TTTT﹕ sendMessage:main
09-17 04:29:48.669  28397-28410/cn.lixyz.handlertest D/TTTT﹕ handleMessage:Thread-141
09-17 04:29:48.669  28397-28410/cn.lixyz.handlertest D/TTTT﹕ 收到了消息对象:100

         上面代码表示,消息是从MainThread发送的,WorkerThread接收到了消息。

         PS:非UI线程默认是没有创建Looper对象的,所以需要主线程向子线程传递消息时,需创建Looper对象并启动循环,子线程才可以循环着从MaessageQueue中取出消息。  

          

         

 

原文地址:https://www.cnblogs.com/xs104/p/4816743.html