1. 子线程调用Handler的boolean sendMessage()方法,最终调用MessageQueue中的boolean enqueueMessage(Message msg, long when) 方法,将msg放入到MessageQueue消息队列中
2. Loop调用public static void loop() 方法,loop()方法会执行一个死循环,不断的调用Message msg = queue.next();方法获取消息,获取到消息后,通过msg.target.dispatchMessage(msg);方法派遣消息,然后dispatchMessage这个方法最终会调用Handler的handlerMessage方法执行我们自己写的逻辑
public final class Looper {
public static void loop() {
final Looper me = myLooper();
...
final MessageQueue queue = me.mQueue;
...
for (;;) {
//相当于获取消息
Message msg = queue.next(); // might block
...
try {
//获取消息后,派遣消息
msg.target.dispatchMessage(msg);
...
}
...
}
}
}
public class Handler {
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
//触发handleMessage处理消息,需要自己实现的方法
handleMessage(msg);
}
}
}
应用开始启动的时候,首先会调用ActivityThread的main方法,main方法会执行一个Looper.prepareMainLooper();初始化Looper
Looper能启动的原因,是因为loop是因为main方法中调用的loop方法,这个方法是一个死循环,这个死循环会不断的轮询msg
main方法中调用Looper.prepareMainLooper();
public final class Looper {
private static Looper sMainLooper; //主Looper
static final ThreadLocal sThreadLocal = new ThreadLocal();
@Deprecated
public static void prepareMainLooper() {
prepare(false);//向ThreadLocal中初始化一个Looper
synchronized (Looper.class) {
if (sMainLooper != null) {//保证了一个线程只能创建一个Looper
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();//sMainLooper的值从ThreadLocal中获取
}
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
}
1. 原因
Handler在调用sendMessage的时候,这个方法会调用到Handler的enqueueMessage方法,这个方法会将Handler赋值给msg的target
MessageQueue持有msg,这时msg对象会持有Handler的引用,Handler中有 this Activity,那么this Activity中大量内存都不会释放,就会造成大量的内存泄漏
如果是一个延迟消息,那么这个消息会一直在MessageQueue中,msg-Handler-this Activity ,那么内存就一直没办法回收
public class Handler {
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
}
2. 解决办法
①将handler声明为静态类,②用软引用或弱引用来持有activity
③在destroy方法里面清理handler中的所有Message
①为什么主线程中可以new Handler
在应用启动的时候,Looper就被初始化好了,在ActivityThread调用Looper.prepareMainLooper();//初始化Looper,在调用Handler的构造器时,会将Looper传给Handler的Looper,构造器没有添加Looper,默认添加主线程的Looper
new Looper源码
public class Handler {
private static final boolean FIND_POTENTIAL_LEAKS = false;
private static final String TAG = "Handler";
private static Handler MAIN_THREAD_HANDLER = null;
...
@UnsupportedAppUsage
final Looper mLooper;
final MessageQueue mQueue;
@UnsupportedAppUsage
final Callback mCallback;
final boolean mAsynchronous;
@UnsupportedAppUsage
IMessenger mMessenger;
...
@Deprecated
public Handler() {
this(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());
}
}
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
}
②如何在子线程中new Handler
用法
HandlerThread handlerThread = new HandlerThread("name");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper()) {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
//...自己实现的方法
}
};
上述代码对应源码解析
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
private @Nullable Handler mHandler;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
protected void onLooperPrepared() {
}
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
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;
}
@NonNull
public Handler getThreadHandler() {
if (mHandler == null) {
mHandler = new Handler(getLooper());
}
return mHandler;
}
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
public int getThreadId() {
return mTid;
}
}
public class Handler {
...
public Handler(@NonNull Looper looper) {
this(looper, null, false);
}
@UnsupportedAppUsage
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
...
}
①当消息队列中没有消息的时候,怎么处理
当消息队列中没有消息的时候,在调用next()函数的时候会休眠,应该调用Looper类的quitSafely()函数,让loop()函数退出;
②作用
当loop()函数退出,这时线程就会退出,线程所占用的资源就都会被释放
如果需要重新发送消息,这时重新创建一个子线程对应的Handler就好,重新创建Looper
Looper类对应源代码如下
public final class Looper {
...
public static void loop() {
final Looper me = myLooper();
...
for (;;) {
//相当于获取消息
Message msg = queue.next();
if (msg == null) {
return;//退出loop()函数
}
...
}
}
}
public final class MessageQueue {
...
@UnsupportedAppUsage
Message next() {
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
nativePollOnce(ptr, nextPollTimeoutMillis);//睡眠
synchronized (this) {
...
if (msg != null) {
...
} else {
nextPollTimeoutMillis = -1;
}
if (mQuitting) {
dispose();
return null;//这里会退出死循环,返回null
}
...
}
...
}
...
}
...
}
Looper类的quitSafety()方法对应源码
public final class Looper {
...
public void quitSafely() {
mQueue.quit(true);
}
...
}
public final class MessageQueue {
...
void quit(boolean safe) {
if (!mQuitAllowed) {
throw new IllegalStateException("Main thread not allowed to quit.");
}
synchronized (this) {
if (mQuitting) {
return;
}
mQuitting = true;
if (safe) {
removeAllFutureMessagesLocked();
} else {
removeAllMessagesLocked();
}
//唤醒因为没有消息而睡眠的线程
nativeWake(mPtr);
}
}
...
private void removeAllMessagesLocked() {
Message p = mMessages;
while (p != null) {
Message n = p.next;
p.recycleUnchecked();
p = n;
}
mMessages = null;
}
//移除掉所有的Message
private void removeAllFutureMessagesLocked() {
final long now = SystemClock.uptimeMillis();
Message p = mMessages;
if (p != null) {
if (p.when > now) {
removeAllMessagesLocked();
} else {
Message n;
for (;;) {
n = p.next;
if (n == null) {
return;
}
if (n.when > now) {
break;
}
p = n;
}
p.next = null;
do {
p = n;
n = p.next;
p.recycleUnchecked();
} while (n != null);
}
}
}
}
③主线程没有消息怎样处理
会一直休眠,必须不可以退出
①多个Handler发消息,如何保证线程安全?
Looper中的MessageQueue是唯一的,多个Handler中的MessageQueue是来自于Looper中的MessageQueue,线程和Looper一一对应,Looper和MessageQueue一一对应,每一个线程只有一个MessageQueue
而且向MessageQueue中添加消息需要加锁,以此来保证线程安全
对应源码
public final class Looper {
...
@UnsupportedAppUsage
final MessageQueue mQueue;
...
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
...
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
}
public class Handler {
...
@UnsupportedAppUsage
final Looper mLooper;
final MessageQueue mQueue;
@UnsupportedAppUsage
final Callback mCallback;
final boolean mAsynchronous;
@UnsupportedAppUsage
IMessenger mMessenger;
...
@UnsupportedAppUsage
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
}
public final class MessageQueue {
@UnsupportedAppUsage
Message mMessages;
...
boolean enqueueMessage(Message msg, long when) {
...
synchronized (this) {
...
}
...
}
}
②取消息,如何保证线程安全
取消息的时候,锁的是MessageQueue,以此来保证取消息线程安全
public final class MessageQueue {
@UnsupportedAppUsage
Message next() {
...
for (;;) {
...
synchronized (this) {
...
}
}
}
}
使用 Message message = Message.obtain(); 创建,这里运用了享元设计模式
public final class Message implements Parcelable {
private static Message sPool;
...
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
...
@UnsupportedAppUsage
void recycleUnchecked() {
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = UID_NONE;
workSourceUid = UID_NONE;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
}
public final class Looper {
public static void loop() {
...
for (;;) {
...
msg.recycleUnchecked();
...
}
}
}
Looper对象调用loop方法的next()方法会阻塞
当一个消息进入队列中的时候,会唤醒阻塞的loop()方法
public final class MessageQueue {
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
synchronized (this) {
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
//将msg插入到消息队列的头部,并将mMessages指向当前msg
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
//队列以时间顺序,从头到尾依次较小,将当前msg插入到合适的位置mMessages
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
}