Android 메시지 메커니즘 문제 요약

안 드 로 이 드 의 메시지 체 제 는 면접 에서 꼭 물 어 봐 야 할 화제 입 니 다.물론 면접 때 문 이 아니 라 공부 하 는 것 입 니 다.더 중요 한 것 은 안 드 로 이 드 개발 에서 없어 서 는 안 될 중요 한 위 치 를 차지 하기 때문에 이 를 이해 하 는 것 이 필요 합 니 다.다음은 가장 기본 적 인 것 을 이야기 하 겠 습 니 다.
Looper
역할:
Thread 연결
순환 추출 메시지
1.Looper 는 직접 예화 할 수 있 습 니까?
Looper 구조 방법 은 사유 적 인 것 으로 그 중에서 두 가지 일 을 했다.
메시지 큐 만 들 기
그 에 대응 하 는 Thread 를 얻 습 니 다.

private Looper(boolean quitAllowed) {
  mQueue = new MessageQueue(quitAllowed);
  mThread = Thread.currentThread();
}
2.하나의 스 레 드 가 여러 개의 Lopper 에 대응 할 수 있 습 니까?
아니요.하나의 스 레 드 는 하나의 Looper 대상 에 대응 합 니 다.ThreadLocal 을 통 해 하나의 스 레 드 가 하나의 Looper 만 대응 하 는 것 을 보증 합 니 다.만약 에 Looper.prepare()를 여러 번 호출 하면;운행 중 이상 을 던 집 니 다.

private static void prepare(boolean quitAllowed) {
  if (sThreadLocal.get() != null) { //      looper       
    throw new RuntimeException("Only one Looper may be created per thread");
  }
  sThreadLocal.set(new Looper(quitAllowed));
}
3、Looper 는 무한 순환 입 니 다.막 힐 까요?
예,loop 을 켜 면 죽은 순환 입 니 다.Message Queue 에서 메 시 지 를 꺼 내 메 시 지 를 처리 하지만 종료 할 수도 있 습 니 다.메시지 가 없 으 면 순환 을 종료 할 수도 있 습 니 다.

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;
    }
//  
    msg.target.dispatchMessage(msg);
  }
4、Looper.prepareMainLooper 를 다시 호출 할 수 있 습 니까?
안 됩 니 다.Looper.prepareMainLooper 도 결국 prepare()를 호출 합 니 다.같은 2.

public static void prepareMainLooper() {
  prepare(false); //     Looper
  synchronized (Looper.class) {
    if (sMainLooper != null) {
      throw new IllegalStateException("The main Looper has already been   prepared.");
    }
    sMainLooper = myLooper();
  }
}
5、MainLooper 는 언제 만 들 었 습 니까?
MainLooper 는 Activity 를 시작 하여 Activity Thread 를 만 들 때 만 들 기 때문에 여러 번 만 들 수 없습니다.

public static void main(String[] args) {
 //  
  Process.setArgV0("<pre-initialized>");
 Looper.prepareMainLooper();
 //  
 ActivityThread thread = new ActivityThread();
 thread.attach(false);
 //  
 if (sMainThreadHandler == null) {
  sMainThreadHandler = thread.getHandler();
 }

 //  
 Looper.loop();
 throw new RuntimeException("Main thread loop unexpectedly exited");
 }
}

Handler
역할:
Message Queue 에 메시지 보 내기
처리 메시지
1.Handler 는 어떻게 Looper,Message Queue 와 연 결 됩 니까?
우 리 는 하나의 Looper 가 하나의 Thread 에 대응 하고 하나의 Looper 는 하나의 Message Queue 를 포함 하고 있다 는 것 을 알 고 있다.Handler 를 만 들 때 현재 스 레 드 에서 해당 하 는 Looper 를 꺼 내 서 Looper 에서 Message Queue 를 꺼 냅 니 다.

// 1、    
public Handler(Callback callback, boolean async) {
 //  
  mLooper = Looper.myLooper(); //         Looper
  if (mLooper == null) {
    throw new RuntimeException(
      "Can't create handler inside thread that has not called    Looper.prepare()");
  }
  mQueue = mLooper.mQueue; //   MessageQueue
  mCallback = callback;
  mAsynchronous = async;
}
// 2、    Looper  
public Handler(Looper looper, Callback callback, boolean async) {
    mLooper = looper;
    mQueue = looper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
  }
Message
단일 링크 구조.
역할:
데이터 캐리어
1.소식 은 어떻게 재 활용 합 니까?
전역 메시지 탱크(링크 구조)에서

public static Message obtain() {
  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();
}
2.Message 는 왜 전 달 됩 니까?
Android 에서 대상 을 전달 하려 면 Serializable 또는 Parcelable 을 실현 하거나 Parcelable 인 터 페 이 스 를 실현 합 니 다.
public final class Message implements Parcelable {
  // 대략.
}
3、Handler 와 어떻게 연결 하나 요?
우 리 는 정보 전달 체제 에서 Handler 가'택배 기사'역할 을 하고 있다 는 것 을 알 고 있다.그러면 그 는 어떻게'화물'-Message 와 관 계 를 맺 었 을 까?실제로 Message 에 멤버 변수 target 이 있 는데 그의 유형 은 Handler 입 니 다.

/*package*/ Runnable callback;

public int arg1; 

public int arg2;

public Object obj;

/*package*/ Handler target; //    
Handler 를 통 해 Message 를 보 낼 때 최종 적 으로 target 에 this,즉 현재 Handler 를 할당 합 니 다.

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
  msg.target = this; //     
  if (mAsynchronous) {
    msg.setAsynchronous(true);
  }
  return queue.enqueueMessage(msg, uptimeMillis);
}
또한 Message.Obtain()을 통 해 얻 은 재 활용 Message 도 값 을 부여 합 니 다.
한 마디 만 더 하 자 면 Handler.obtainMessage()가 호출 한 것 이 Message.Obtain()이다.

public final Message obtainMessage(){
  return Message.obtain(this);
}
요약:
일련의 포용 관 계 를 통 해 최종 적 으로 Looper,Handler,Message,Message Queue 는 관련 이 발생 하여 하나의 폐쇄 를 형성 하고 메시지 순환 을 엽 니 다.

곤혹스럽다
최근 에 이 분야 의 지식 을 계속 보고 있 지만 능력 에 한계 가 있어 서 곤 혹 스 럽 습 니 다.만약 에 잘못 이 있 거나 다음 문 제 를 이해 하면 저 에 게 연락 하 세 요[email protected].............................................
1.Message 의 sPool,어디서 초기 화 되 었 습 니까?왜 Message.obtain()에서 이상 을 던 지지 않 습 니까?
2.Activity Thread 는 스 레 드 가 아 닙 니 다.왜 Looper 를 만 들 수 있 습 니까?Main Thread 는 언제 만 듭 니까?
3.왜 서열 화 된 대상 이 전달 되 나 요?Binder 와 관련 이 있다 고요?
4.Message Queue 는 NativeMessage Queue 에 대응 하 는데 구체 적 으로 실현 하려 면 공부 해 야 합 니까?
5、Loop.loop(),탈퇴 하나 요?탈퇴 타 이 밍 이 뭐 예요?종료 된다 면 메 인 스 레 드 도 종료 되 나 요?
이상 은 안 드 로 이 드 메시지 체제 에 대한 자료 정리 입 니 다.추 후 관련 자 료 를 계속 보충 하 겠 습 니 다.본 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다.

좋은 웹페이지 즐겨찾기