行到水穷处,坐看云起时。–>王维
new Thread(new Runnable() {
@Override
public void run() {
Handler handler = new Handler();
}
}).start();
运行会抛出
Can’t create handler inside thread Thread[Thread-2,5,main] that has
not called Looper.prepare()
异常。跟踪到handler的构造方法里发现
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());
}
}
//取存储在sThreadLocal中的looper()对象
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()的时候,并没有Looper,导致抛出了异常。
new Thread(new Runnable() {
@Override
public void run() {
//先通过这个静态方法创建looper,并存储在sThreadLocal中.
Looper.prepare();
Handler handler = new Handler();
}
}).start();
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
以上我们就创建好了messageQueue,Looper和Handler,可以愉快的玩耍了。
1.调用Looper.loop();开启循环,消息机制开始运转
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
mHandler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
// super.handleMessage(msg);
if (msg.what ==1){
Toast.makeText(MainActivity.this,msg.obj.toString(),Toast.LENGTH_SHORT).show();
}
}
};
Looper.loop();
}
}).start();
Message message = Message.obtain();
message.what = 1;
message.obj = "haha";
mHandler.sendMessage(message);
最后调用handleMessage处理消息
/**
* Handle system messages here.
*/
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
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("" );
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();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
通过Looper.prepareMainLooper()来创建主线程的Looper以及MessageQueue,并通过Looper.loop();来开启主线程的消息循环。
class H extends Handler {
public static final int BIND_APPLICATION = 110;
@UnsupportedAppUsage
public static final int EXIT_APPLICATION = 111;
@UnsupportedAppUsage
public static final int RECEIVER = 113;
@UnsupportedAppUsage
public static final int CREATE_SERVICE = 114;
...
}
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));
}