其他
Android消息机制Handler原理解析
本文字数:4454字
预计阅读时间:15分钟
导读
需求背景
2
3 public void handleMessage(Message msg) {
4 super.handleMessage(msg);
5 LogUtils.d("腾讯云Imi handler out --");
6 if (TLSService.getInstance() != null && TLSService.getInstance().getLastUserIdentifier() != null) {
7 isIMNotinit = false;
8 presenter.getUnreadNum(getContext());
9 presenter.getConversation(getContext(), true);
10 LogUtils.d("腾讯云Imi handler");
11 }
12 }
13 };
2 private WeakReference<Context> mContextReference;
3
4 public MyHandler(Context c) {
5 mContextReference = new WeakReference<Context>(c);
6 }
7
8
9 public void handleMessage(Message msg) {
10 final Context c = mContextReference.get();
11 if (c != null) {
12 if (CommonUtils.notEmpty(msg.obj.toString())) {
13 Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
14 Uri uri = Uri.fromFile(new File(msg.obj.toString()));
15 intent.setData(uri);
16 c.sendBroadcast(intent); // 发送广播通知相册
17 }
18 Toast.makeText(c, "图片下载完成", Toast.LENGTH_SHORT).show();
19 }
20 }
21 }
22private static class MyHandler extends Handler {
23 private WeakReference<Context> mContextReference;
24
25 public MyHandler(Context c) {
26 mContextReference = new WeakReference<Context>(c);
27 }
28
29
30 public void handleMessage(Message msg) {
31 final Context c = mContextReference.get();
32 if (c != null) {
33 if (CommonUtils.notEmpty(msg.obj.toString())) {
34 Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
35 Uri uri = Uri.fromFile(new File(msg.obj.toString()));
36 intent.setData(uri);
37 c.sendBroadcast(intent); // 发送广播通知相册
38 }
39 Toast.makeText(c, "图片下载完成", Toast.LENGTH_SHORT).show();
40 }
41 }
42 }
43private static class MyHandler extends Handler {
44 private WeakReference<Context> mContextReference;
45
46 public MyHandler(Context c) {
47 mContextReference = new WeakReference<Context>(c);
48 }
49
50
51 public void handleMessage(Message msg) {
52 final Context c = mContextReference.get();
53 if (c != null) {
54 if (CommonUtils.notEmpty(msg.obj.toString())) {
55 Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
56 Uri uri = Uri.fromFile(new File(msg.obj.toString()));
57 intent.setData(uri);
58 c.sendBroadcast(intent); // 发送广播通知相册
59 }
60 Toast.makeText(c, "图片下载完成", Toast.LENGTH_SHORT).show();
61 }
62 }
63 }
消息发送
2 Message msg = Message.obtain();
3 msg.what = what;
4 return sendMessageDelayed(msg, delayMillis);
5}
2{
3 return sendEmptyMessageDelayed(what, 0);
4}
2 Message msg = Message.obtain();
3 msg.what = what;
4 return sendMessageDelayed(msg, delayMillis);
5}
2 MessageQueue queue = mQueue;
3 if (queue == null) {
4 RuntimeException e = new RuntimeException(
5 this + " sendMessageAtTime() called with no mQueue");
6 Log.w("Looper", e.getMessage(), e);
7 return false;
8 }
9 return enqueueMessage(queue, msg, 0);
10 }
2 MessageQueue queue = mQueue;
3 if (queue == null) {
4 RuntimeException e = new RuntimeException(
5 this + " sendMessageAtTime() called with no mQueue");
6 Log.w("Looper", e.getMessage(), e);
7 return false;
8 }
9 return enqueueMessage(queue, msg, uptimeMillis);
10}
2 if (FIND_POTENTIAL_LEAKS) {
3 final Class<? extends Handler> klass = getClass();
4 if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
5 (klass.getModifiers() & Modifier.STATIC) == 0) {
6 Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
7 klass.getCanonicalName());
8 }
9 }
10
11 mLooper = Looper.myLooper();
12 if (mLooper == null) {
13 throw new RuntimeException(
14 "Can't create handler inside thread that has not called Looper.prepare()");
15 }
16 mQueue = mLooper.mQueue;
17 mCallback = callback;
18 mAsynchronous = async;
19 }
2 return sThreadLocal.get();
3}
2 if (sThreadLocal.get() != null) {
3 throw new RuntimeException("Only one Looper may be created per thread");
4 }
5 sThreadLocal.set(new Looper(quitAllowed));
6}
7
8private Looper(boolean quitAllowed) {
9 mQueue = new MessageQueue(quitAllowed);
10 mThread = Thread.currentThread();
11 }
2 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
3 SamplingProfilerIntegration.start();
4
5 // CloseGuard defaults to true and can be quite spammy. We
6 // disable it here, but selectively enable it later (via
7 // StrictMode) on debug builds, but using DropBox, not logs.
8 CloseGuard.setEnabled(false);
9
10 Environment.initForCurrentUser();
11
12 // Set the reporter for event logging in libcore
13 EventLogger.setReporter(new EventLoggingReporter());
14
15 // Make sure TrustedCertificateStore looks in the right place for CA certificates
16 final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
17 TrustedCertificateStore.setDefaultUserDirectory(configDir);
18
19 Process.setArgV0("<pre-initialized>");
20
21 Looper.prepareMainLooper();
22
23 ActivityThread thread = new ActivityThread();
24 thread.attach(false);
25
26 if (sMainThreadHandler == null) {
27 sMainThreadHandler = thread.getHandler();
28 }
29
30 if (false) {
31 Looper.myLooper().setMessageLogging(new
32 LogPrinter(Log.DEBUG, "ActivityThread"));
33 }
34
35 // End of event ActivityThreadMain.
36 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
37 Looper.loop();
38
39 throw new RuntimeException("Main thread loop unexpectedly exited");
40 }
2 prepare(false);
3 synchronized (Looper.class) {
4 if (sMainLooper != null) {
5 throw new IllegalStateException("The main Looper has already been prepared.");
6 }
7 sMainLooper = myLooper();
8 }
9}
消息存储与消息循环
2 if (msg.target == null) {
3 throw new IllegalArgumentException("Message must have a target.");
4 }
5 if (msg.isInUse()) {
6 throw new IllegalStateException(msg + " This message is already in use.");
7 }
8
9 synchronized (this) {
10 if (mQuitting) {
11 IllegalStateException e = new IllegalStateException(
12 msg.target + " sending message to a Handler on a dead thread");
13 Log.w(TAG, e.getMessage(), e);
14 msg.recycle();
15 return false;
16 }
17
18 msg.markInUse();
19 msg.when = when;
20 Message p = mMessages;
21 boolean needWake;
22 if (p == null || when == 0 || when < p.when) {
23 // New head, wake up the event queue if blocked.
24 msg.next = p;
25 mMessages = msg;
26 needWake = mBlocked;
27 } else {
28 // Inserted within the middle of the queue. Usually we don't have to wake
29 // up the event queue unless there is a barrier at the head of the queue
30 // and the message is the earliest asynchronous message in the queue.
31 needWake = mBlocked && p.target == null && msg.isAsynchronous();
32 Message prev;
33 for (;;) {
34 prev = p;
35 p = p.next;
36 if (p == null || when < p.when) {
37 break;
38 }
39 if (needWake && p.isAsynchronous()) {
40 needWake = false;
41 }
42 }
43 msg.next = p; // invariant: p == prev.next
44 prev.next = msg;
45 }
46
47 // We can assume mPtr != 0 because mQuitting is false.
48 if (needWake) {
49 nativeWake(mPtr);
50 }
51 }
52 return true;
53 }
2 final Looper me = myLooper();
3 if (me == null) {
4 throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
5 }
6 final MessageQueue queue = me.mQueue;
7
8 // Make sure the identity of this thread is that of the local process,
9 // and keep track of what that identity token actually is.
10 Binder.clearCallingIdentity();
11 final long ident = Binder.clearCallingIdentity();
12
13 for (;;) {
14 Message msg = queue.next(); // might block
15 if (msg == null) {
16 // No message indicates that the message queue is quitting.
17 return;
18 }
19
20 // This must be in a local variable, in case a UI event sets the logger
21 final Printer logging = me.mLogging;
22 if (logging != null) {
23 logging.println(">>>>> Dispatching to " + msg.target + " " +
24 msg.callback + ": " + msg.what);
25 }
26
27 final long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
28
29 final long traceTag = me.mTraceTag;
30 if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
31 Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
32 }
33 final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
34 final long end;
35 try {
36 msg.target.dispatchMessage(msg);
37 end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
38 } finally {
39 if (traceTag != 0) {
40 Trace.traceEnd(traceTag);
41 }
42 }
43 if (slowDispatchThresholdMs > 0) {
44 final long time = end - start;
45 if (time > slowDispatchThresholdMs) {
46 Slog.w(TAG, "Dispatch took " + time + "ms on "
47 + Thread.currentThread().getName() + ", h=" +
48 msg.target + " cb=" + msg.callback + " msg=" + msg.what);
49 }
50 }
51
52 if (logging != null) {
53 logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
54 }
55
56 // Make sure that during the course of dispatching the
57 // identity of the thread wasn't corrupted.
58 final long newIdent = Binder.clearCallingIdentity();
59 if (ident != newIdent) {
60 Log.wtf(TAG, "Thread identity changed from 0x"
61 + Long.toHexString(ident) + " to 0x"
62 + Long.toHexString(newIdent) + " while dispatching to "
63 + msg.target.getClass().getName() + " "
64 + msg.callback + " what=" + msg.what);
65 }
66
67 msg.recycleUnchecked();
68 }
69 }
2 if (msg.callback != null) {
3 handleCallback(msg);
4 } else {
5 if (mCallback != null) {
6 if (mCallback.handleMessage(msg)) {
7 return;
8 }
9 }
10 handleMessage(msg);
11 }
12 }
2 if (Thread.currentThread() != mUiThread) {
3 mHandler.post(action);
4 } else {
5 action.run();
6 }
7}
2 final AttachInfo attachInfo = mAttachInfo;
3 if (attachInfo != null) {
4 return attachInfo.mHandler.post(action);
5 }
6
7 // Postpone the runnable until we know on which thread it needs to run.
8 // Assume that the runnable will be successfully placed after attach.
9 getRunQueue().post(action);
10 return true;
11}
总结
也许你还想看
(▼点击文章标题或封面查看)
2018-08-30
2019-04-18
2018-08-16
加入搜狐技术作者天团
千元稿费等你来!
戳这里!☛