美文网首页
让主线程给子线程发送消息

让主线程给子线程发送消息

作者: 咸鱼Jay | 来源:发表于2017-06-22 17:25 被阅读671次

    一般我们遇到最多的都是让子线程给主线程发送消息,这种方式我就不说了,今天来说说,主线程给子线程发送消息。

    1、首先我们在Activity中的onCreate方法中开启一个子线程,然后在子线程中进行Looper和Handler的创建等

    @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    /**
                     *  1、创建了Looper对象,然后Looper对象中创建了MessageQueue
                     *  2、并将当前的Looper对象跟当前的线程(子线程)绑定ThreadLocal
                     */
                    Looper.prepare();
    
                    /**
                     * 1、创建Handler对象,然后从当前线程中获取Looper对象,然后获取到MessageQueue对象
                     */
                    subHandler = new Handler(){
                        @Override
                        public void handleMessage(Message msg) {
                            super.handleMessage(msg);
                            Toast.makeText(MainActivity.this,msg.obj.toString(),Toast.LENGTH_LONG).show();
                        }
                    };
    
                    /**
                     * 1、从当前线程中找到之前创建的Looper对象,然后找到MessageQueue
                     * 2、开启死循环,遍历消息池中的消息
                     * 3、当获取到msg的时候,调用这个msg的handler的dispatchMsg方法,让msg执行起来
                     */
                    Looper.loop();
                    Log.e("zxj","loop()方法执行完了");
                }
            }).start();
        }
    

    2、然后在点击事件中发送消息

    public void onSendClick(View v){
        //从消息池中获取一个旧的msg,如果没有,重新创建消息
        Message message = subHandler.obtainMessage(1, "我是主线程发送来是消息");
        message.sendToTarget();
    }
    

    3、问题

    以上的写法还是存在一些问题的,其实你在运行起来后,点击按钮发送消息后,当你退出当前Activity后,发现上面定义的log日志,没有执行,这就说明,那个子线程一直未执行完,为啥呢?其实就是因为loop()这个方法,因为这个方法就一个死循环的,所以这个方法一直在循环中,从而导致子线程一直没有执行完,最终会导致内存泄露

    4、解决方法

    在子线程中拿到创建的Looper对象(Looper.myLooper()),然后在onDestroy中中止loop方法

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(myLooper != null)
            myLooper.quit();
    }
    

    5、最终代码

    public class MainActivity extends AppCompatActivity {
        private Handler subHandler;//是在子线程中创建的Handler对象
        private Looper myLooper;//子线程中的Looper对象
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
          
            new Thread(new Runnable() {
                @Override
                public void run() {
                    /**
                     *  1、创建了Looper对象,然后Looper对象中创建了MessageQueue
                     *  2、并将当前的Looper对象跟当前的线程(子线程)绑定ThreadLocal
                     */
                    Looper.prepare();
    
                    /**
                     * 1、创建Handler对象,然后从当前线程中获取Looper对象,然后获取到MessageQueue对象
                     */
                    subHandler = new Handler(){
                        @Override
                        public void handleMessage(Message msg) {
                            super.handleMessage(msg);
                            Toast.makeText(MainActivity.this,msg.obj.toString(),Toast.LENGTH_LONG).show();
                        }
                    };
    
                    //获取当前线程中的Looper对象
                    myLooper = Looper.myLooper();
    
                    /**
                     * 1、从当前线程中找到之前创建的Looper对象,然后找到MessageQueue
                     * 2、开启死循环,遍历消息池中的消息
                     * 3、当获取到msg的时候,调用这个msg的handler的dispatchMsg方法,让msg执行起来
                     */
                    Looper.loop();
                    Log.e("zxj","loop()方法执行完了");
                }
            }).start();
        }
    
        public void onSendClick(View v){
            //从消息池中获取一个旧的msg,如果没有,重新创建消息
            Message message = subHandler.obtainMessage(1, "我是主线程发送来是消息");
            message.sendToTarget();
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            if(myLooper != null)
                myLooper.quit();
        }
    }
    

    相关文章

      网友评论

          本文标题:让主线程给子线程发送消息

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