사실, 인터넷은 아주 좋은 잘 쓰여진 글을 많이 가지고,이 뇌졸중 분명 생각이다 쓰고, 기억을 강화하고 싶었다.
여기에 훌륭한 기사를 추천합니다 :
https://blog.csdn.net/zip_tts/article/details/86097136#commentBox
메시지 핸들러 메커니즘은 주로 다섯 개 가지 구성 요소, 핸들러, 자벌레, 메시지, MessageQueue가,의 ThreadLocal을 가지고
- 메시지 핸들러로 메시지를 처리하고 메시지를 보내기위한 처리 센터입니다.
- 메일 메시지를 취득하는 전력 메시지로서 루퍼.
- 메시지를 운반 캐리어와 같은 메시지 메시지.
- 메시지를 저장하는 메시지 대기열로 MessageQueue가.
- ThreadLocal를 내부 스레드 클래스 데이터를 저장하고, 데이터는 지정된 thread 얻을 수있다.
**
첫째, 메시지 것입니다
무엇보다도, 메시지 전송이 내부에 무엇 무엇을 우리가 원하는 이해합니다.
public final class Message implements Parcelable {
public int what;
public int arg1;
public int arg2;
public Object obj;
public Messenger replyTo;
int flags;
long when;
Bundle data;
Handler target;
}
당신은 아주 익숙한 느낌이되지 않습니다? 우리는 필요가 사용되는 방법을 많이 씁니다.
여기에 대상이고, 핸들러는 우리가 나중에 이해하는 데 도움이 메시지 핸들러의 메시지를 저장하는 것입니다의 유형입니다.
두, 핸들러 및 전송 인스턴스화
핸들러 일곱 생성자의 예
public Handler() {
this(null, false);
}
public Handler(Callback callback) {
this(callback, false);
}
public Handler(Looper looper) {
this(looper, null, false);
}
public Handler(Looper looper, Callback callback) {
this(looper, callback, false);
}
public Handler(boolean async) {
this(null, async);
}
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;
}
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
우리는 지정되지 않은 경우 스레드 루퍼 루퍼는 처리기를 인스턴스화하는 데 사용되는 코드에서 볼 수 있습니다.
사실, 핸들러를 보내는 소개가 많은 방법이 있습니다,하지만 모양은 마지막 방법을 지시하는 enqueueMessage 찾을 수 있습니다, 메시지 메시지 캡슐화 된 후 발송.
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
상기 코드 자체에 대상 점의 메시지는 상기에 송신 MessageQueue가, 음) (이하이 MessageQueue가 enququqMessage 분석 이해
三, MessageQueue가
부울 enqueueMessage (메시지 MSG, 긴 경우) {
경우 (msg.target == NULL) {
( "메시지가 대상이 있어야합니다.") 새, IllegalArgumentException를 throw;
}
경우 (msg.isInUse ()) {
( "이 메시지는 이미 사용 중입니다."MSG +) 새로운 IllegalStateException을 발생;
}
synchronized (this) {
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
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 {
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;
}
사실, 메시지 큐, 지연이 순차적으로 설정되어 있지 않은 경우, 링크 된 목록에 저장된 시간에 메시지가, 시간이 분류 것이다.
네, 루퍼
다음은 루퍼 생성자입니다 :
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
그런 다음 그것을 확실히 당신이 얻을 수있는 다른 방법이 될 것입니다, 즉, 루퍼는 객체를 생성하는 새로운 방법으로하지 않습니다 그것의 생성자는 개인 것을 볼 수 있습니다. 방법을 준비,이 prepareMainLooper 그 안에있는 소스 코드를 볼 계속,
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
루퍼 prepareMainLooper 주로 항상 주 스레드 자벌레가 있기 때문에, 정상적인 상황에서, 금지, 메인 쓰레드를 생성하는 데 사용됩니다. 그리고 당신은 () 만들거나 준비하는 주요 방법을 볼 수 있습니다.
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));
}
그 곳의 ThreadLocal입니다
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
분명히, 이것은 스레드 루퍼의 출력을 생성하고, ThreadLocal을 유지 할 수 있습니다.
그래서 지금 루퍼는 사용이 메시지 MessageQueue가로 보낼 방법을 만들었습니다? 그의 루프 ()
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;
}
// This must be in a local variable, in case a UI event sets the logger
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
try {
msg.target.dispatchMessage(msg);
end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
}
나는 거의 핵심 코드 위에, 몇 가지 코드를 삭제. MessageQueue가 본질적으로 하나의리스트에, 루프는 그것을 직접 비우 돌아가거나 경우 메시지 MessageQueue가 옆 통과 정지, 무한 루프입니다 (;;)에 사용되는 msg.target.dispatchMessage(msg)
핸들러 msg.target에 정보를 전송 dispatchMessage의 이동으로 입력합니다.
다섯, 핸들러 수집 및 처리
그런 다음 코드는 dispatchMessage의 핸들러에 온 ()에서
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
여기에 몇 가지 판단 문이다. 핸들러에서,이 방법은의 메시지를 처리하는 것입니다, 인터페이스 콜백이 한 방향으로 만의 handleMessage이 선언 콜백 생성자에 전달. 방법이 있는지 생성자에서 들어오는 콜백이 핸들러는 또한 handleMessage 메소드를 정의하지 않는 경우는 물론, 기본값은 빈 구현입니다. 이것은 메시지 오버라이드이 방법에 의해 처리 될 수있다.
그래서이 모든 과정이 끝났다.