目录
相关视频:
相关文章:
一、Handler理解:(参照以上视频内容)
二、Handler的使用:
(一)、异常展示:
(二)、使用Runnable:
(三)、使用sendMessage():
(四)、使用sendMessage() 传递实体类:
三、源码解析:
Android面试常客Handler详解
Handler用法及解析
Handler的作用与用法
当你创建一个新的Handler的时候,它是被一个Thread创建的,这个新的Handler会和这个Thread绑定,同时这个Handler也会被绑定到这个Thread的MessageQueue当中。
当一个Application被创建的时候,就会创建一个Main Thread,在Android中也就是ActivityThread,也就是我们常说的UI线程。
private MyThread myThread;
private void method5() {
myThread = new MyThread();
myThread.start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
myThread.handler.sendEmptyMessage(1);
handler5.sendEmptyMessage(1);
}
@SuppressLint("HandlerLeak")
private Handler handler5 = new Handler() {
@Override
public void handleMessage(Message msg) {
/**
* 默认与UI线程进行关联
* 因此不能做一些耗时操作
*/
LogUtils.e("UI线程ID为:" + Thread.currentThread());
}
};
/**
* 当你创建一个新的Handler的时候,它是被一个Thread创建的,这个新的Handler会和这个Thread绑
定,
* 同时这个Handler也会被绑定到这个Thread的MessageQueue当中。
*
* 当一个Application被创建的时候,就会创建一个Main Thread,在Android中也就是
ActivityThread,也就是我们常说的UI线程。
*/
class MyThread extends Thread {
public Handler handler;
public Looper looper;
@SuppressLint("HandlerLeak")
@Override
public void run() {
Looper.prepare();
looper = Looper.myLooper();
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
LogUtils.e("当前线程id为:" + Thread.currentThread());
}
};
Looper.loop();
}
}
以下为打印结果:
主要方法:
sendMessage(Message msg)
sendMessageDelayed(Message msg, long delayMillis)
post(Runnable r)
postDealyed(Runnable r, long uptimeMillis)
其他方法:
obtainMessage()
post(Runnable r)
postAtTime(Runnable r, long uptimeMillis)
sendMessage(Message msg)
sendMessageDelayed(Message msg, long delayMillis)
sendMessageAtTime(Message msg, long uptimeMillis)
sendEmptyMessage(int what)
sendEmptyMessageDelayed(int what, long delayMillis)
sendEmptyMessageAtTime(int what, long uptimeMillis)
android.view.ViewRootImpl$CalledFromWrongThreadException:
Only the original thread that created a view hierarchy can touch its views.
代码:
new Thread(){
@Override
public void run() {
try {
Thread.sleep(1000);
textView.setText("update");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
private Handler handler1 = new Handler();
private void method2() {
new Thread() {
@Override
public void run() {
try {
Thread.sleep(1000);
handler1.post(new Runnable() {
@Override
public void run() {
textView.setText("update");
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
private Handler handler3 = new Handler() {
@Override
public void handleMessage(Message msg) {
textView.setText(msg.arg1 + "");
}
};
private void method3() {
new Thread() {
@Override
public void run() {
try {
Thread.sleep(2000);
Message message = handler3.obtainMessage();
message.arg1 = 1;
handler3.sendMessage(message);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
在这里,不建议直接new Message,Message内部保存了一个缓存的消息池,我们可以用obtain从缓存池获得一个消息,Message使用完后系统会调用recycle回收,如果自己new很多Message,每次使用完后系统放入缓存池,会占用很多内存的。
以下是对obtainMessage的源码解析:
Message message = handler.obtainMessage();
public final Message obtainMessage() {
//此处的this就是Handler
return Message.obtain(this);
}
Handler target;
public static Message obtain(Handler h) {
//创建一个Message,并将这个Message指定给一个target,这个target就是Handler自己,
// 意思就是说把Message发送给Handler自己
Message m = obtain();
m.target = h;
return m;
}
private static final Object sPoolSync = new Object();
private static Message sPool;
private static int sPoolSize = 0;
Message next;
int flags;
public static Message obtain() {
//先尝试取出一个空的Message对象,如果没有就新建一个
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();
}
@SuppressLint("HandlerLeak")
private Handler handler4 = new Handler() {
@SuppressLint("SetTextI18n")
@Override
public void handleMessage(Message msg) {
textView.setText(msg.obj.toString());
}
};
private void method4() {
new Thread() {
@Override
public void run() {
try {
Thread.sleep(1000);
Message message = handler3.obtainMessage();
message.obj = new Person(23, "zhang san");
handler4.sendMessage(message);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
class Person {
public int age;
public String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
我们知道在Handler调用之前是要进行Looper.prepare(),那么我们在实际使用过程中,往往没有写这个代码,是怎么回事呢,
原来, ActivityThread即主线程已经帮我们做这件事情了
public final class ActivityThread {
public static void main(String[] args) {
Looper.prepareMainLooper();
}
}
public final class Looper {
static final ThreadLocal sThreadLocal = new ThreadLocal();
private static Looper sMainLooper; // guarded by Looper.class
final MessageQueue mQueue;
final Thread mThread;
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));
}
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
}
然后我们新建Handler,就可以直接使用了:
private Handler handler=new Handler();
public class Handler {
final android.os.Looper mLooper;
final MessageQueue mQueue;
public Handler() {
this(null, false);
}
public Handler(android.os.Handler.Callback callback, boolean async) {
mLooper = android.os.Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
}
public static @Nullable
android.os.Looper myLooper() {
return sThreadLocal.get();
}
}
比较关键的是这两个方法:
public final class Looper {
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 class Handler {
public Handler(android.os.Handler.Callback callback, boolean async) {
mLooper = android.os.Looper.myLooper();
}
public static @Nullable android.os.Looper myLooper() {
return sThreadLocal.get();
}
}
通过ThreadLocal 先set一个Looper,然后再get这个Looper。