【Android】App通信基础架构相关类源码解析

应用通信基础架构相关类源码解析

这里主要对Android App开发时,常用到的一些通信基础类进行一下源码的简单分析,包括:

  • Handler:处理器,与某个Looper(一个线程对应一个Looper)进行关联。用于接收消息,并在关联的Looper,处理消息。
  • Looper:驱动器,驱动基于事件的消息系统(通信架构的核心)其实现在Native层,基于epoll机制(感兴趣的可自行了解)。
  • Runnable: 表示"可执行的代码",本质是Interface,规定了Run这个接口。
  • MessageQueue: 消息队列,提供了入队、出队等操作。一个线程,只能有一个MessageQueue。
  • Thread: 线程类,封装了线程相关操作。

基于Android12代码。

类图:

Handler

常见用法

java 复制代码
private Handler mHandler = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(Message msg) {
		// 处理消息
    }
};

private void sendMessage() {
    // 发送消息
    Message msg = mHandler.obtainMessage();
	// 填充msg
    mHandler.sendMessage(msg);
}

private void postRunnable() {
	// 告知Handler一段可执行的代码(Runnable)
    mHandler.post(new Runnable() {
        @Override
        public void run() {
            // do something
        }
    });
}

通过上述代码中,可以看出。创建Handler时需要绑定Looper,也就是绑定到运行的线程上。如过不指定looper,使用创建handler时所在线程的Looper。

源码定义在 frameworks/base/core/java/android/os/Handler.java

java 复制代码
public Handler() {
    this(null, false);
}

public Handler(@NonNull Looper looper) {
    this(looper, null, false);
}

public Handler(@Nullable Callback callback, boolean async) {
    if (FIND_POTENTIAL_LEAKS) {
        final Class<? extends Handler> klass = getClass();
        if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                (klass.getModifiers() & Modifier.STATIC) == 0) {
            Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                klass.getCanonicalName());
        }
    }

	// 获取当前线程对应的Looper
    mLooper = Looper.myLooper();
    if (mLooper == null) {
        throw new RuntimeException(
            "Can't create handler inside thread " + Thread.currentThread()
                    + " that has not called Looper.prepare()");
    }
    // 使用Looper中的MessageQueue
    mQueue = mLooper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

@UnsupportedAppUsage
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
    mLooper = looper;
    mQueue = looper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

调用Handler的sendMessage,到Handler处理(handleMessage)这个Message。Handler会将这个Message,入队到绑定的Looper的MessageQueue(消息队列中)。

java 复制代码
public final boolean sendMessage(@NonNull Message msg) {
	 // 没有延时 
     return sendMessageDelayed(msg, 0);
}

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

public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
    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);
}

private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
        long uptimeMillis) {
    msg.target = this;
    // 记录一下UID
    msg.workSourceUid = ThreadLocalWorkSource.getUid();

    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    // 消息入队MessageQueue
    return queue.enqueueMessage(msg, uptimeMillis);
}

Looper从MessageQueue中依次取出Message,并告知Handler的handleMessage处理消息(想要看懂looper,涉及到其Native实现,这里不分析,可自行了解)

Looper

Looper类基于epoll机制,提供了一套事件驱动机制。Java层的实现在frameworks/base/core/java/android/os/Looper.java ,该类中的sMainLooper变量存储了 主线程 (或者叫UI线程)对应的Looper,可以通过getMainLooper取得。

java 复制代码
public final class Looper {
    private static final String TAG = "Looper";

    // sThreadLocal.get() will return null unless you've called prepare().
    @UnsupportedAppUsage
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    @UnsupportedAppUsage
    private static Looper sMainLooper;  // guarded by Looper.class
    // 省略
    public static Looper getMainLooper() {
       synchronized (Looper.class) {
           return sMainLooper;
       }
   }
}

常见的用法,比如在自定义的线程中。

java 复制代码
public class MyThread extends Thread {  
  
    private Handler mHandler;  
  
    @Override  
    public void run() {  
        Looper.prepare(); // 准备Looper  
  
        mHandler = new Handler() {  
            @Override  
            public void handleMessage(Message msg) {  
                // 处理消息  
                }  
            }  
        };  
  
        Looper.loop(); // 开始循环,等待消息  
    }
}

Looper的实现这里就不分析了,路径在**/frameworks/base/core/java/android/os/Looper.java**,可自行了解(建议先掌握epoll)

Thread

Android Thread类提供线程功能,其定义在 libcore/ojluni/src/main/java/java/lang/Thread.java

java 复制代码
public
class Thread implements Runnable {
   public Thread() {
        init(null, null, "Thread-" + nextThreadNum(), 0);
    }
}

调用start方法,可以启动线程,比如上面定义的MyThread类。

java 复制代码
MyThread thr = new MyThread();
thr.start();

其提供了一些方法,用于控制线程,比如

  • sleep: 让线程等待一段时间
  • jion:等待线程退出(或者叫执行完成)
  • interrupt:打断线程。

注意:Thread和Looper是两个事情,其关系是一对一。 Thread就是常规意义上的线程,程序代码最小的运行单位(先不考虑协程),Looper是一套基于消息(事件)的驱动机制。

Runnable是一个接口类,规定了Run这个方法。MessageQueue是一个消息队列。这个类功能比较单一。其源码路径如下,感兴趣的可自行了解。

  • /frameworks/base/core/java/android/os/MessageQueue.java
  • /libcore/ojluni/src/main/java/java/lang/Runnable.java

再贴一遍类图,加深理解。

相关推荐
腥臭腐朽的日子熠熠生辉28 分钟前
解决maven失效问题(现象:maven中只有jdk的工具包,没有springboot的包)
java·spring boot·maven
Harrison_zhu29 分钟前
Ubuntu18.04 编译 Android7.1代码报错
android
ejinxian30 分钟前
Spring AI Alibaba 快速开发生成式 Java AI 应用
java·人工智能·spring
杉之35 分钟前
SpringBlade 数据库字段的自动填充
java·笔记·学习·spring·tomcat
圈圈编码1 小时前
Spring Task 定时任务
java·前端·spring
俏布斯1 小时前
算法日常记录
java·算法·leetcode
27669582921 小时前
美团民宿 mtgsig 小程序 mtgsig1.2 分析
java·python·小程序·美团·mtgsig·mtgsig1.2·美团民宿
爱的叹息1 小时前
Java 连接 Redis 的驱动(Jedis、Lettuce、Redisson、Spring Data Redis)分类及对比
java·redis·spring
程序猿chen1 小时前
《JVM考古现场(十五):熵火燎原——从量子递归到热寂晶壁的代码涅槃》
java·jvm·git·后端·java-ee·区块链·量子计算
松韬2 小时前
Spring + Redisson:从 0 到 1 搭建高可用分布式缓存系统
java·redis·分布式·spring·缓存