我们在开发中经常用到的在子线程中执行耗时任务,然后通过Handler到主线程中更新UI。我们对它都很熟悉,今天再来复习一下这个Handler。下面几种方式是今天要复习的

rxjava 在子线程执行任务 如何在子线程中创建handler_Thread

 (1)单向的子线程与子线程交互:即由一个子线程向另一个子线程发送消息;

需要先创建一个新的子线程,然后在子线程内创建Handler,来接收另一个子线程发来的消息。在子线程中创建Handler必须要先获取Looper,否则程序则会崩溃,并且会报错误:Can't create handler inside thread that has not called Looper.prepare()。Handler消息机制源码详解参考这篇文章:https://www.jianshu.com/p/750e3706c467

/*
      (1)子线程与子线程交互(单向)。
       创建一个新的子线程
     */
    class MyThread1 extends Thread{
        public Handler mHandler1;

        @Override
        public void run() {
            super.run();
            //1.实例化当前线程的Looper,每个线程只能有一个Looper实例。
            Looper.prepare();
            //2.创建Handler
            mHandler1 = new Handler(){
                @Override
                public void handleMessage(@NonNull Message msg) {
                    super.handleMessage(msg);
                    switch (msg.what){
                        case 0:
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    tv_receivedMsg.setText("(1)子线程中使用Handler向另一个子线程发消息(单向)");
                                }
                            });
                            break;
                    }
                }
            };
            //3.开启Looper循环接收消息
            Looper.loop();
        }
    }

之后由一个线程向这个新线程发送消息

private MyThread1 myThread1;
        
        myThread1 = new MyThread1();
        myThread1.start();

                new Thread(){
                    @Override
                    public void run() {
                        super.run();
                        myThread1.mHandler1.sendEmptyMessage(0);
                    }
                }.start();

(2)两个子线程互发消息(双向):需要创建两个线程并相互发送消息

/*
      (2)两个子线程互发消息(双向)
       即创建两个线程,并在一个线程发送消息到另一个线程处理
     */
    class MyThread21 extends Thread{
        public Handler mHandler21;
        @Override
        public void run() {
            super.run();
            //1.实例化当前线程的Looper,每个线程只能有一个Looper实例。
            Looper.prepare();
            //2.创建Handler
            mHandler21 = new Handler(){
                @Override
                public void handleMessage(@NonNull Message msg) {
                    super.handleMessage(msg);
                    switch (msg.what){
                        case 20:
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    tv_receivedMsg.setText("收到");
                                    //收到消息,使用MyThread22的mHandler22向MyThread22发送消息
                                    myThread22.mHandler22.sendEmptyMessage(22);
                                }
                            });
                            break;
                        case 21:
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    try {
                                        Thread.sleep(2000);
                                        //收到MyThread22发来的消息
                                        tv_receivedMsg.setText("(2)两个子线程互发消息(双向)\n 线程1收到MyThread22发来的消息");
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                }
                            });
                            break;
                    }
                }
            };
            //3.开启Looper循环接收消息
            Looper.loop();
        }
    }

    class MyThread22 extends Thread{
        public Handler mHandler22;
        @Override
        public void run() {
            super.run();
            //1.实例化当前线程的Looper,每个线程只能有一个Looper实例。
            Looper.prepare();
            //2.创建Handler
            mHandler22 = new Handler(){
                @Override
                public void handleMessage(@NonNull Message msg) {
                    super.handleMessage(msg);
                    switch (msg.what){
                        case 22:
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    tv_receivedMsg.setText("(2)两个子线程互发消息(双向)\n 线程2收到myThread21发来的消息");
                                    try {
                                        Thread.sleep(2000);
                                        //收到myThread21发来的消息,使用myThread21的mHandler21向myThread21发消息
                                        myThread21.mHandler21.sendEmptyMessage(21);
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                }
                            });
                            break;
                    }
                }
            };
            //3.开启Looper循环接收消息
            Looper.loop();
        }
    }

执行这两线程互相发送消息

private MyThread21 myThread21;
    private MyThread22 myThread22;

    myThread21 = new MyThread21();
    myThread22 = new MyThread22();
    myThread21.start();
    myThread22.start();

    myThread21.mHandler21.sendEmptyMessage(20);

(3)主线程发送消息到子线程:先创建一个子线程

//(3)主线程发消息到子线程
    class MyThread3 extends Thread{
        public Handler mHandler3;

        @Override
        public void run() {
            super.run();
            //1.实例化当前线程的Looper,每个线程只能有一个Looper实例。
            Looper.prepare();
            //2.创建Handler
            mHandler3 = new Handler(){
                @Override
                public void handleMessage(@NonNull Message msg) {
                    super.handleMessage(msg);
                    switch (msg.what){
                        case 0:
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    tv_receivedMsg.setText("(3)子线程收到主线程发来的消息");
                                }
                            });
                            break;
                    }
                }
            };
            //3.开启Looper循环接收消息
            Looper.loop();
        }
    }

然后由主线程向新建的子线程发送消息

private MyThread3 myThread3;

    myThread3 = new MyThread3();
    myThread3.start();

    myThread3.mHandler3.sendEmptyMessage(0);

(4)子线程发送消息主线程:这个也是我们平时最常用的

//子线程发送消息主线程
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        mHandler.sendEmptyMessage(4);
                    }
                }).start();

在主线程中创建Handler来接收消息

Handler mHandler = new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case 4:
                    tv_receivedMsg.setText("主线程收到子线程发来的消息");
                    break;
            }
        }
    };

(5)附加一个handler.post的使用,可直接在run里面更新UI。Handler的sendMessage和post的区别可参考这篇文章:https://www.jianshu.com/p/43d6cd7b06f1

mHandler.post(new Runnable() {
    @Override
    public void run() {
        tv_receivedMsg.setText("handler.post通过实现Runnable接口,直接更新UI");
    }
});

整个复习测试的完整源程序

public class HandlerTestActivity extends AppCompatActivity {

    View viewStatus;
    private Button btn_handler1,btn_handler2,btn_handler3,btn_handler4;
    private Button btn_handlerPost;
    private TextView tv_receivedMsg;

    private MyThread1 myThread1;

    private MyThread21 myThread21;
    private MyThread22 myThread22;

    private MyThread3 myThread3;

    Handler mHandler = new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case 4:
                    tv_receivedMsg.setText("主线程收到子线程发来的消息");
                    break;
            }
        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_test);
        initView();
        initData();
        initListener();
    }

    private void initView(){
        if (Build.VERSION.SDK_INT >= 21) {
            View decorView =getWindow().getDecorView();
            int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
            decorView.setSystemUiVisibility(option);
            //这上面是颜色
            getWindow().setStatusBarColor(Color.TRANSPARENT); //也可以设置成灰色透明的,比较符合Material Design的风格
        }
        viewStatus = findViewById(R.id.view_status);
        ViewGroup.LayoutParams layoutParams = viewStatus.getLayoutParams();
        layoutParams.height = getStatusBarHeight();

        btn_handler1 = findViewById(R.id.btn_handler1);
        btn_handler2 = findViewById(R.id.btn_handler2);
        btn_handler3 = findViewById(R.id.btn_handler3);
        btn_handler4 = findViewById(R.id.btn_handler4);
        btn_handlerPost = findViewById(R.id.btn_handlerPost);
        tv_receivedMsg = findViewById(R.id.tv_receivedMsg);
    }

    private void initData(){
        /**
         * (1)子线程与子线程交互(单向)。
         */
        myThread1 = new MyThread1();
        myThread1.start();

        /**
         * (2)两个子线程互发消息(双向)
         */
        myThread21 = new MyThread21();
        myThread22 = new MyThread22();
        myThread21.start();
        myThread22.start();

        /**
         * (3)主线程发送消息到子线程。
         */
        myThread3 = new MyThread3();
        myThread3.start();
    }

    private void initListener(){
        //子线程中使用Handler向另一个子线程发消息(单向)
        btn_handler1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(){
                    @Override
                    public void run() {
                        super.run();
                        myThread1.mHandler1.sendEmptyMessage(0);
                    }
                }.start();
            }
        });

        btn_handler2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myThread21.mHandler21.sendEmptyMessage(20);
            }
        });

        btn_handler3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myThread3.mHandler3.sendEmptyMessage(0);
            }
        });

        btn_handler4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //子线程发送消息主线程
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        mHandler.sendEmptyMessage(4);
                    }
                }).start();
            }
        });

        //Handler.post的使用
        btn_handlerPost.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        tv_receivedMsg.setText("handler.post通过实现Runnable接口,直接更新UI");
                    }
                });
            }
        });
    }

    /*
      (1)子线程与子线程交互(单向)。
       创建一个新的子线程
     */
    class MyThread1 extends Thread{
        public Handler mHandler1;

        @Override
        public void run() {
            super.run();
            //1.实例化当前线程的Looper,每个线程只能有一个Looper实例。
            Looper.prepare();
            //2.创建Handler
            mHandler1 = new Handler(){
                @Override
                public void handleMessage(@NonNull Message msg) {
                    super.handleMessage(msg);
                    switch (msg.what){
                        case 0:
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    tv_receivedMsg.setText("(1)子线程中使用Handler向另一个子线程发消息(单向)");
                                }
                            });
                            break;
                    }
                }
            };
            //3.开启Looper循环接收消息
            Looper.loop();
        }
    }

    /*
      (2)两个子线程互发消息(双向)
       即创建两个线程,并在一个线程发送消息到另一个线程处理
     */
    class MyThread21 extends Thread{
        public Handler mHandler21;
        @Override
        public void run() {
            super.run();
            //1.实例化当前线程的Looper,每个线程只能有一个Looper实例。
            Looper.prepare();
            //2.创建Handler
            mHandler21 = new Handler(){
                @Override
                public void handleMessage(@NonNull Message msg) {
                    super.handleMessage(msg);
                    switch (msg.what){
                        case 20:
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    tv_receivedMsg.setText("收到");
                                    //收到消息,使用MyThread22的mHandler22向MyThread22发送消息
                                    myThread22.mHandler22.sendEmptyMessage(22);
                                }
                            });
                            break;
                        case 21:
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    try {
                                        Thread.sleep(2000);
                                        //收到MyThread22发来的消息
                                        tv_receivedMsg.setText("(2)两个子线程互发消息(双向)\n 线程1收到MyThread22发来的消息");
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                }
                            });
                            break;
                    }
                }
            };
            //3.开启Looper循环接收消息
            Looper.loop();
        }
    }

    class MyThread22 extends Thread{
        public Handler mHandler22;
        @Override
        public void run() {
            super.run();
            //1.实例化当前线程的Looper,每个线程只能有一个Looper实例。
            Looper.prepare();
            //2.创建Handler
            mHandler22 = new Handler(){
                @Override
                public void handleMessage(@NonNull Message msg) {
                    super.handleMessage(msg);
                    switch (msg.what){
                        case 22:
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    tv_receivedMsg.setText("(2)两个子线程互发消息(双向)\n 线程2收到myThread21发来的消息");
                                    try {
                                        Thread.sleep(2000);
                                        //收到myThread21发来的消息,使用myThread21的mHandler21向myThread21发消息
                                        myThread21.mHandler21.sendEmptyMessage(21);
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                }
                            });
                            break;
                    }
                }
            };
            //3.开启Looper循环接收消息
            Looper.loop();
        }
    }

    //(3)主线程发消息到子线程
    class MyThread3 extends Thread{
        public Handler mHandler3;

        @Override
        public void run() {
            super.run();
            //1.实例化当前线程的Looper,每个线程只能有一个Looper实例。
            Looper.prepare();
            //2.创建Handler
            mHandler3 = new Handler(){
                @Override
                public void handleMessage(@NonNull Message msg) {
                    super.handleMessage(msg);
                    switch (msg.what){
                        case 0:
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    tv_receivedMsg.setText("(3)子线程收到主线程发来的消息");
                                }
                            });
                            break;
                    }
                }
            };
            //3.开启Looper循环接收消息
            Looper.loop();
        }
    }

    @Override
    protected void onDestroy() {
        if (null != myThread1.mHandler1){
            myThread1.mHandler1.removeCallbacksAndMessages(null);
        }
        if (null != myThread21.mHandler21){
            myThread21.mHandler21.removeCallbacksAndMessages(null);
        }
        if (null != myThread22.mHandler22){
            myThread22.mHandler22.removeCallbacksAndMessages(null);
        }
        if (null != myThread3.mHandler3){
            myThread3.mHandler3.removeCallbacksAndMessages(null);
        }
        super.onDestroy();
    }
}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/background"
    android:orientation="vertical">

    <View
        android:id="@+id/view_status"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="#01012A" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:text="Handler的交互场景"
        android:background="@color/colorPrimary"
        android:gravity="center"
        android:textSize="18dp"
        android:textColor="@color/white"/>

    <Button
        android:id="@+id/btn_handler1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="(1)子线程与子线程交互(单向)"/>
    <Button
        android:id="@+id/btn_handler2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="(2)两个子线程互发消息(双向)"/>

    <Button
        android:id="@+id/btn_handler3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="(3)主线程发送消息到子线程"/>

    <Button
        android:id="@+id/btn_handler4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="(4)子线程发送消息主线程"/>

    <Button
        android:id="@+id/btn_handlerPost"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="(5)handlerPost方法"
        android:textAllCaps="false"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="接收消息:"
        android:textSize="18dp"
        android:textColor="@color/white"/>
    <TextView
        android:id="@+id/tv_receivedMsg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="16dp"
        android:textColor="@color/blueP"/>

</LinearLayout>