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

2017-06-22  本文已影响671人  咸鱼Jay

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

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();
    }
}
上一篇下一篇

猜你喜欢

热点阅读