作为一个开发小白,我以前写代码是这样的
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
......
}
};
但是有个问题
This Handler class should be static or leaks might occur (anonymous android.os.Handler)
这个Handler class应该是static,否则可能会内存泄漏。学习了新的写法。
private static class MyHandler extends Handler {
//保持对Activity的引用
private final WeakReference<MainActivity> mActivityWeakReference;
//通过构造方法传入Activity
public MyHandler(MainActivity activity) {
mActivityWeakReference = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
BaseActivity activity = mActivityWeakReference.get();
if (activity == null) {
super.handleMessage(msg);
return;
}
switch (msg.what) {
case DOWNLOAD_FAILED:
....
break;
case DOWNLOAD_SUCCESS:
.....
break;
default:
super.handleMessage(msg);
break;
}
}
}
使用的时候直接调用
private final MyHandler mHandler = new MyHandler(this);
//使用Handler进行延时操作,实际上发送的也是Message
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
imageView.setVisibility(View.VISIBLE);
}
},1000);
//使用子线程下载图片
new Thread(new Runnable() {
@Override
public void run() {
Bitmap bitmap = downloadImage();
Message msg = Message.obtain();
msg.obj = bitmap;
msg.what = bitmap==null?DOWNLOAD_FAILED:DOWNLOAD_SUCCESS;
handler.sendMessage(msg);
}
}).start();
所以我决定看一下学习一下Handler的机制。
为什么postDelayed()发送的也是Message?
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean postDelayed(Runnable r, long delayMillis)
{
//方法1
return sendMessageDelayed(getPostMessage(r), delayMillis);
}
/**
* 方法1
*/
private static Message getPostMessage(Runnable r) {
//获取消息,到这里我们就明白了为什么是Message了
Message m = Message.obtain();
m.callback = r;
return m;
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
/**
* 除了sendMessageAtFrontOfQueue()方法之外,其它的发送消息方法最终都会走到这里
*/
public boolean sendMessageAtTime(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;
}
//sendMessageAtFrontOfQueue返回的是enqueueMessage(queue, msg, 0);
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
//先看一下Message再看怎么消息排列
return queue.enqueueMessage(msg, uptimeMillis);
}
Message
作用:包含任意数据对象的消息,用于发送给Handler
获取Message实例的方式
//获取Message实例的方式
Message msg1 = new Message();
Message msg1 = Message.obtain();
Message msg2 = Handler.obtainMessage();
public final class Message implements Parcelable {
/**
* 用户自定义消息码
*/
public int what;
/**
* arg1和arg2是Message自带的用来传递一些轻量级存储int类型的数据,比如进度条的数据等。
* 通过这个数据是通过Bundle的方式来转载的
*/
public int arg1;
public int arg2;
/**
* 用来传递一些对象
*/
public Object obj;
/**
* 线程通信时候使用
*/
public Messenger replyTo;
....
}
/**
* 平时获取消息会调用此方法,sPool为当前消息对象池,sPool实际就是单项链表
* 当sPool = null的时候才会new Message(),如果不是,就从sPool里面拿实例
*/
public static Message obtain() {
//锁对象,在定义时候初始化,随后只读不写
synchronized (sPoolSync) {
if (sPool != null) {
//典型的链表结构
//比如 原本消息是 1(sPool) - 2(m.next) - 3 取走了1
//现在就剩下 2(sPool) - 3了
Message m = sPool; //
sPool = m.next; //相当于把2置顶
m.next = null; // 相当于把原来的1的下一个节点引用置为null,因为此时m.next(1)还在指向2
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
//如果对象池中没有就返回一个新的Message
return new Message();
}
MessageQueue
/**
* 用于将消息排队,提供消息入队的方法
* when 就是SystemClock.uptimeMillis() + delayMillis,就是你创建消息的时间+你要延迟的时间
*/
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
//判断是否退出
msg.markInUse();
msg.when = when;
//以前的消息链表的头部
Message p = mMessages;
boolean needWake;
//什么时候为when == 0 呢? 就是使用sendMessageAtFrontOfQueue
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 {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
//一直循环判断时间,确定合适的位置
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;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
//需要唤醒发送就调用底层线程间通信发送(现在还没了解=-=)
nativeWake(mPtr);
}
}
return true;
}
void recycleUnchecked() {
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = -1;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
//把前一个Message存起来置为当前Message的next
next = sPool;
//把当前的Message放在最前面
sPool = this;
sPoolSize++;
}
}
}
ActivityThread:
public static void main(String[] args) {
....
//初始化主线程Looper
Looper.prepareMainLooper();
....
//系统启动的时候就会执行looper的loop方法
Looper.loop();
}
Looper:
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
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));
}
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
....
//一直循环
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
....
try {
//分发消息,调用Handler的dispatchMessage方法内部调用的是我们常常重写的handleMessage方法
msg.target.dispatchMessage(msg);
....
} finally {
...
}
....
//回收一些资源
msg.recycleUnchecked();
}
}
ThreadLocal
ThreadLocal并不是本地线程,而是线程本地变量
就是使Looper在不同的线程下获取的值不同,主线程是主线程的,Thread1是Thread1的
使用场景:当某些数据时以线程为作用域而且不同的线程获得的数据不同
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
void createMap(Thread t, T firstValue) {
//可见Thread中有个ThreadLocalMap
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
/**
* 专门存放要进行本地化的线程数据的Map
*/
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
table = new Entry[INITIAL_CAPACITY];
//这里放的位置和HashMap的计算方式一样,可以去看HashMap的原理
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
table[i] = new Entry(firstKey, firstValue);
size = 1;
//设置阈(yu)值
setThreshold(INITIAL_CAPACITY);
}
/**
* 存值操作,有了Map就直接存值
*/
private void set(ThreadLocal<?> key, Object value) {
// We don't use a fast path as with get() because it is at
// least as common to use set() to create new entries as
// it is to replace existing ones, in which case, a fast
// path would fail more often than not.
Entry[] tab = table;
int len = tab.length;
//这里还是和HashMap一样,,,可见HashMap中用了多么巧妙的算法
int i = key.threadLocalHashCode & (len-1);
for (Entry e = tab[i];
e != null;//循环的时候判断是否e为空
e = tab[i = nextIndex(i, len)] // 如果e != null 那么就存到i + 1的位置,如果超过了大小就放在0
) {
ThreadLocal<?> k = e.get();
//从弱引用中获取值
if (k == key) {
e.value = value;
return;
}
if (k == null) {
//替换Entry
replaceStaleEntry(key, value, i);
return;
}
}
//tab[i] 为空,也就是表中没有这个数据
tab[i] = new Entry(key, value);
int sz = ++size;
//更新了数据而且数据量过大了就重新hash
if (!cleanSomeSlots(i, sz) && sz >= threshold)
rehash();
}
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
总结一下
用下郭霖大神的图。
Handler流程图.png明白了原来有些事情需要我们去钻研。去深入,给自己加油 打call~!
网友评论