首先定义三个个Hander,一个在主线程的Handler,两个个在子线程的Handler
- 在主线程的Handler定义如下
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == MSG_MAIN) {
LogUtils.e(TAG, "handler1====" + Thread.currentThread().getName());
}
super.handleMessage(msg);
}
};
Message message = handler.obtainMessage();
message.what = MSG_MAIN;
handler.sendMessage(message);
执行后的日志如下
handler1====main
- 在子线程的Handler定义如下
new Thread(new Runnable() {
@Override
public void run() {
handler2 = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == MSG_THREAD) {
LogUtils.e(TAG, "handler2========" + Thread.currentThread().getName());
}
}
};
Message message2 = handler2.obtainMessage();
message2.what = MSG_THREAD;
handler2.sendMessage(message2);
}
}).start();
执行后日志如下:
handler2========main
- 在子线程定义的Handler如下
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
Handler handler3 = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == MSG_THREAD_NEW) {
LogUtils.e(TAG, "handler3========" + Thread.currentThread().getName());
}
}
};
handler3.sendEmptyMessage(MSG_THREAD_NEW);
Looper.loop();
}
}).start();
执行后日志如下:
handler3========Thread-5
总结:主线程可以直接使用定义Handler且执行在主线程,如果在子线程定义Handler,并使用Hanlder(Looper.getMainLooper()),则发送的消息也是在主线程执行;如果在子线程定义Handler使用,需要使用Loop.prepare();定义完Handler后,Loop.loop(),则发送的消息在子线程执行
public Handler(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;
}
- 创建Handler时,要确定Looper是否为null,如果是null,则报错
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
- 获取Looper是通过ThreadLocal<Looper> 变量获取,子线程使用Handler时,Looper.prepare(),是初始化
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));
}
主线程为什么不需要Looper.prepare,因为在ActivityThread的Main方法中,有初始化
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
// Make sure TrustedCertificateStore looks in the right place for CA certificates
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("<pre-initialized>");
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();
- 其中Looper.prepareMainLooper()已经创建了一个Looper,并且执行了Looper.loop()
Looper内的for死循环为什么不卡死
网友评论