美文网首页
22.通过Handler实现线程间通信

22.通过Handler实现线程间通信

作者: Jsonzhang | 来源:发表于2017-05-20 12:56 被阅读76次

    前言

    主线程可以向子线程发送消息吗?如果可以怎样实现?
    子线程可以向子线程发送消息吗?
    面试时被面试官问过两次这样的问题都没有回答上来,所以今天查阅了一些资料来补充一下这里的知识。

    参考资料:http://www.mamicode.com/info-detail-517314.html

    子线程向主线程发送消息

    由于android不允许在主线程做耗时的操作,子线程又不能更新UI,所以我们工作中大多用的都是在子线程中请求处理数据,然后将数据发送到主线程,来更新UI,所以我们经常用到的都是子线程向主线程发送消息,大家都不陌生就不多说了。

    主线程向子线程发送消息

    我们首先要确定一个事情:哪个线程要处理消息,Handler就必须绑定到哪个线程

    其实简单的逻辑就是创建一个Handler,然后在一个线程中发送消息,另一个线程中处理消息。Handler将消息发送到消息队列MessageQueue中,消息队列是由Looper来负责管理的,所以我们首先要得到一个Looper。但是有的同学就有疑问了,为啥我们平时写代码时没有管什么looper啊,那是因为我们在主线程创建的Handler,而主线程默认帮我们完成了Looper的操作,所以如果我们从主线程向子线程发送消息,Handler是子线程的的,我们必须在子线程中自己完成Looper的操作。

    我们再来具体的说下这个Looper是什么。
    它就像一个消息队列(MessageQueue)的管家(Looper),一个消息队列只有一个管家,并且管理者整个消息队列,而一个消息队列内可以容纳多个消息(Message),而工人(Handler)也可以有多个,管家派遣他们向消息队列中存储或取出消息后执行任务;

    所以它们的个数如下:
    管家(Looper): 1 个;
    消息队列(MessageQueue):1 个;
    消息(Message):可以多个;
    工人(Handler):可以多个;

    Looper的部分源码:

    //ThreadLocal可以理解为一个存储Looper的列表;
    ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    
    //Looper的构造器
    private Looper(boolean quitAllowed) {
            mQueue = new MessageQueue(quitAllowed);
            mThread = Thread.currentThread();
        }
    
    
    1.Looper.prepare()完成了如下操作:
    sThreadLocal.set(new Looper(quitAllowed));
    
    
    2.Looper.loop()完成了如下操作:
    Looper me = sThreadLocal.get();
    
    MessageQueue queue = me.mQueue;
    ……
    //不断循环分发消息
    for (;;) {
        Message msg = queue.next(); 
        ……
        msg.target.dispatchMessage(msg);
    
            //dispatchMessage(msg)方法执行如下内容:
            handler.handleMessage(msg);//handler执行handleMessage(msg)中的代码;
        ……
    };
    

    简单实例

    public class MainActivity extends AppCompatActivity {
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            final MyThread thread = new MyThread();
            thread.start();
    
            findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Message message = Message.obtain();
                    message.what = 2;
                    thread.handler.sendMessage(message);
                }
            });
    
    
        }
    
        class MyThread extends Thread{
            private Handler handler;
    
            @Override
            public void run() {
                super.run();
                Looper.prepare();
                handler = new Handler(){   //handler必须在在线程的run方法中创建
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                        Toast.makeText(MainActivity.this,"MyThread handler 收到消息 :"+msg.what,Toast.LENGTH_LONG).show();
                    }
                };
                Looper.loop();
            }
        }
    }
    
    

    Looper.prepare() 和Looper.loop() 就是所说的我们要在子线程中要自己完成的Looper操作。

    子线程向子线程发送消息

     class MyThread extends Thread{
            public Handler handler;
    
            @Override
            public void run() {
                super.run();
                Looper.prepare();
                handler = new Handler(){   //handler必须在在线程的run方法中创建
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                        Toast.makeText(MainActivity.this,"MyThread handler 收到消息 :"+msg.what,Toast.LENGTH_LONG).show();
                    }
                };
                Looper.loop();
            }
        }
    

    其实只要我们知道了上面的和代码,建立一个线程类,先获取Looper对象,然后在run方法中绑定一个Handler,然后启动消息循环,我们就可以在任何时间地点通过创建线程类对象,从而获取他的handler成员变量来发送消息。所以子线程也可以向子线程发送消息。

    public class MainActivity extends AppCompatActivity {
        YourThread yourThread;
        MyThread myThread;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    yourThread = new YourThread();
                    yourThread.start();
                }
            });
    
            myThread = new MyThread();
            myThread.start();
        }
    
        class MyThread extends Thread{
            private Handler handler;
    
            @Override
            public void run() {
                super.run();
                Looper.prepare();
                handler = new Handler(){   //handler必须在在线程的run方法中创建
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                        Toast.makeText(MainActivity.this,"MyThread handler 收到消息 :"+msg.what,Toast.LENGTH_LONG).show();
                    }
                };
    
                Looper.loop();
            }
        }
    
        class YourThread extends Thread{
            @Override
            public void run() {
                super.run();
                Message message = Message.obtain();
                message.what = 3;
                myThread.handler.sendMessage(message);
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:22.通过Handler实现线程间通信

          本文链接:https://www.haomeiwen.com/subject/mgtpxxtx.html