一般线程的消息传递过程

745 阅读2分钟

「这是我参与2022首次更文挑战的第14天,活动详情查看:2022首次更文挑战」。

一般线程消息传递过程

主线程Looper的来源

之前已经说过了主线程的消息处理过程,但是之前还有一个问题,就是主线程的Looper是怎么来的?我们之前在ContentProvider的介绍中说过,程序的主线程是ActivityThread,app的入口是其main方法,在这个方法中会重新持有一个ActivityThread的对象。
显然,答案需要我们到ActivityThread的main方法中去寻找

public static void main(String[] args) {
...
    Looper.prepareMainLooper();

    // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
    // It will be in the format "seq=114"
    long startSeq = 0;
    if (args != null) {
        for (int i = args.length - 1; i >= 0; --i) {
            if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
                startSeq = Long.parseLong(
                        args[i].substring(PROC_START_SEQ_IDENT.length()));
            }
        }
    }
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

    if (false) {
        Looper.myLooper().setMessageLogging(new
                LogPrinter(Log.DEBUG, "ActivityThread"));
    }

    // End of event ActivityThreadMain.
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    Looper.loop();

    throw new RuntimeException("Main thread loop unexpectedly exited");
}

源代码比较长,这里只截取部分代码,可以发现这里有一个prepareMainLooper()和loop()方法,这两个方法也就是我们之前介绍的Looper的两个主要方法(一般线程是prepare()方法),其中prepareMainLooper()方法如下

@Deprecated
public static void prepareMainLooper() {
    prepare(false);
    synchronized (Looper.class) {
        if (sMainLooper != null) {
            throw new IllegalStateException("The main Looper has already been prepared.");
        }
        sMainLooper = myLooper();
    }
}

其本质还是用prepare方法在主线程的ThreadLocalMap中添加Looper。

一般线程的消息机制

从主线程的消息机制来看,一个线程如果要使用android的消息机制那么必须具备几个条件,Looper,ThreadLocal,MessageQueue,Handler,其中ThreadLocal是线程创建的时候就有的,MessageQueue是Looper创建的时候创建的,因此,也就只剩下Looper和Handler需要我们自己手动添加(Main线程甚至只需要添加Handler就好)。 所以过程如下:

new Thread(new Runnable() {
    @Override
    public void run() {
        Looper.prepare();
         Handler handler = new Handler(new Handler.Callback() {
            @Override
            public boolean handleMessage(@NonNull Message msg) {
                Log.d("message",(String)msg.obj);
                return false;
            }
        });
        new Thread(new Runnable() {
            @Override
            public void run() {
                Message message = new Message();
                message.obj = "abc";
                handler.sendMessage(message);
            }
        }).start();
        Looper.loop();
    }
}).start();

首先需要prepare()方法为当前线程添加Looper,接着添加一个事件处理的Handler,最终在线程结尾处不断从消息队列中取得Message进行处理。

总结

至此,整个android的消息传递机制稍微简单地介绍了一遍,总的来说需要记住这么几个类或者对象,ThreadLocal,ThreadLocal.ThreadLocalMap,Looper,MessageQueue,Handler,Thread,ActivityThread,AcitivityThread的main方法,记住这几个点后,然后梳理它们的关系,这样就可以将点连成线,梳理出整个脉络