Android消息处理机制

Android消息处理机制

相关源码路径:

frameworks/base/core/java/android/os/Looper.java
frameworks/base/core/java/android/os/Handler.java
frameworks/base/core/java/android/os/HandlerThread.java
frameworks/base/core/java/android/os/Message.java
libcore/libart/src/main/java/java/lang/Thread.java

一、消息处理机制基本流程

主线程:

  • 创建、启动子线程
  • 构造Handler,包含要发送给子线程的消息和消息的处理函数
  • 发送消息:Handler.sendMessage, sendEmptyMessageAtTime, sendMessageDelayed

子线程:

  • 创建消息队列 MessageQueue –> Looper.perpare();
  • 使用Looper循环处理消息 –> Looper.loop();

二、多线程编程

Thread类有多种构造方法
这里写图片描述

1.实现Runnable接口,run方法在线程启动后运行:

class MyRunnable implements Runnable {
   public void run () {
       int count = 0;
       for (;;) {
           Log.d(TAG, "MyThread1 "+count);
           count++;
           try {
               Thread.sleep(3000);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
   }
}

2.创建并启动线程myThread1:

myThread1 = new Thread(new MyRunnable(), "MessageTestThread");
myThread1.start();

三、消息处理(自己的线程类)

1.编写自己的线程类

    class MyThread extends Thread {
        private Looper mLooper;
        @Override
        /* run方法在线程start后执行 */
        public void run() {
            super.run();
            Looper.prepare();/* 创建消息队列*/
            /* 防止myThread2.start后,还没run起来就去执行new Handler,导致getLooper出错,这里仿造HandlerThread的方法*/
            synchronized (this) {
                mLooper = Looper.myLooper();
                notifyAll();
            }
            Looper.loop();/* 循环处理消息 */
        }

        /* mLooper是创建Handler需要的参数 */
        public Looper getLooper(){
            if (!isAlive()) {
                return null;
            }

            // If the thread has been started, wait until the looper has been created.
            synchronized (this) {
                while (isAlive() && mLooper == null) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                    }
                }
            }
            return mLooper;
        }
    }

在onCreate中创建、启动线程myThread2:

myThread2 = new MyThread();
myThread2.start();
  1. 构造Handler,包含要发送给子线程的消息和消息的处理函数
/* 参数是:Handler要发送的目标线程的Looper和消息的处理函数 */
mHandler2 = new Handler(myThread2.getLooper(), new Handler.Callback() {
    @Override
    public boolean handleMessage(Message msg) {
        Log.d(TAG, "get Message for Thread2 ");
        return false;
    }
});

3.再button中发送消息

Message msg = new Message();
mHandler2.sendMessage(msg);

sendMessage的实现:

public final boolean sendMessage(Message msg)
{
    return sendMessageDelayed(msg, 0);
}

public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
    if (delayMillis < 0) {
        delayMillis = 0;
    }
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}

public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
    /* 最终将消息发送到mQueue队列中 */
    MessageQueue queue = mQueue;
    if (queue == null) {
        RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue");
        Log.w("Looper", e.getMessage(), e);
        return false;
    }
    return enqueueMessage(queue, msg, uptimeMillis);
}

mQueue在构造Handler的时候被赋值,所以消息将发送到线程的looper对应的消息队列中:

mHandler2 = new Handler(myThread2.getLooper(), new Handler.Callback() {
    @Override
    public boolean handleMessage(Message msg) {
        Log.d(TAG, "get Message for Thread2");
        return false;
    }
});
==>
public Handler(Looper looper, Callback callback) {
    this(looper, callback, false);
}
==>
public Handler(Looper looper, Callback callback, boolean async) {
    mLooper = looper;
    /* 传进来的线程的looper.mQueue */
    mQueue = looper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

四、消息处理(HandlerThread线程类)

1.在onCreate中创建、启动线程myThread3:

myThread3 = new HandlerThread("MessageTestThread3");
myThread3.start();
  1. 构造Handler,包含要发送给子线程的消息和消息的处理函数
mHandler3 = new Handler(myThread3.getLooper());
  1. 发送消息(post方法)
mHandler3.post(new Runnable() {
    @Override
    public void run() {
        Log.d(TAG, "get Message for Thread3 "+ mMessageCount);
        mMessageCount++;
    }
});

完整代码:

package com.thisway.app_addons_0001_message;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.view.View;
import android.util.Log;
import android.os.HandlerThread;

public class MainActivity extends AppCompatActivity {

    private Button mButton;
    private final String TAG="MessageTest";
    private int ButtonCount = 0;
    private Thread myThread1;
    private MyThread myThread2;
    private Handler mHandler2;
    private Handler mHandler3;
    private int mMessageCount = 0;
    private HandlerThread myThread3;

    class MyRunnable implements Runnable {
        public void run () {
            int count = 0;
            for (;;) {
                Log.d(TAG, "MyThread1 "+count);
                count++;
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    class MyThread extends Thread {
        private Looper mLooper;
        @Override
        public void run() {
            super.run();
            Looper.prepare();
            synchronized (this) {
                mLooper = Looper.myLooper();
                notifyAll();
            }
            Looper.loop();
        }

        public Looper getLooper(){
            if (!isAlive()) {
                return null;
            }

            // If the thread has been started, wait until the looper has been created.
            synchronized (this) {
                while (isAlive() && mLooper == null) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                    }
                }
            }
            return mLooper;
        }
    }

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

        mButton = (Button)findViewById(R.id.button);
        mButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                // Perform action on click
                Log.d(TAG, "Button: Send Message "+ ButtonCount);
                ButtonCount++;
                Message msg = new Message();
                mHandler2.sendMessage(msg);

                mHandler3.post(new Runnable() {
                    @Override
                    public void run() {
                        Log.d(TAG, "get Message for Thread3 "+ mMessageCount);
                        mMessageCount++;
                    }
                });
            }
        });

        myThread1 = new Thread(new MyRunnable(), "MessageTestThread");
        myThread1.start();

        myThread2 = new MyThread();
        myThread2.start();

        mHandler2 = new Handler(myThread2.getLooper(), new Handler.Callback() {
            @Override
            public boolean handleMessage(Message msg) {
                Log.d(TAG, "get Message for Thread2");
                return false;
            }
        });

        myThread3 = new HandlerThread("MessageTestThread3");
        myThread3.start();
        mHandler3 = new Handler(myThread3.getLooper());
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

最后附上一些深入的帖子:
Android应用程序消息处理机制(Looper、Handler)分析

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值