Android Handler 메시지 순환 에 대한 심도 있 는 분석

6719 단어 androidhandler
Handler 는 스 레 드 내부 의 메시지 대기 열 을 조작 하 는 클래스 입 니 다.이것 은 좀 복잡 하 다.괜찮아,우리 천천히 말 하 자.앞에서 Looper 한 편 은 Looper 가 스 레 드 에 메시지 큐 를 만 드 는 데 사용 된다 고 말 했다.즉,Looper 는 메시지 큐(Message Queue)를 스 레 드 에 부속 시 키 고 메시지 큐 를 순환 시 켜 메 시 지 를 받 고 처리 할 수 있다 는 것 이다.그러나 저 희 는 메시지 대기 열 을 직접 조작 하지 않 고 Handler 로 메시지 대기 열 을 조작 하여 메시지 대기 열 에 메 시 지 를 보 내 고 메시지 대기 열 에서 메 시 지 를 꺼 내 처리 합 니 다.이것 이 바로 Handler 의 직책 이다.Handler,Looper,Message Queue 는 하나의 스 레 드 내부 에 속 하 는 데이터 이지 만 외부 스 레 드 에 접근 하 는 인 터 페 이 스 를 제공 합 니 다.Handler 는 외부 스 레 드 에 공개 되 고 스 레 드 와 통신 하 는 인터페이스 입 니 다.다시 말 하면 이 세 가 지 는 모두 라인 간 통신 용(ITC-Inter Thread Communication)으로 진 행 된 통신(IPC-Inter Process Communication)의 메시지 대기 열 msgque 의 핵심 사상 과 일치한다.Message Queue 는 상대 적 으로 밑바닥 이 고 직접 사용 하 는 것 이 적 으 며 Looper 와 Handler 는 밑바닥 Message Queue 를 전문 적 으로 조작 하 는 것 이다.또 하나의 중요 한 데이터 구 조 는 통신 의 기본 요소 인 메시지 대상(Message)이다.Message 는 단독으로 사용 하지 않 고 모두 Handler 를 따라 사용한다.구체 적 인 방법 은 문 서 를 참고 할 수 있 지만 주의해 야 할 것 은 같은 메시지 대상 이 두 번 보 낼 수 없다 는 것 입 니 다.그렇지 않 으 면 AndroidRuntime Exception:{what=1000 when=-15ms obj=..}This message is already in use 가 있 습 니 다."매번 메 시 지 를 보 내기 전에 Message.obtain()을 통 해 새로운 대상 을 가 져 오 거나,추가 데 이 터 를 전송 하지 않 아 도 되 는 빈 메 시 지 를 직접 보 내 면 됩 니 다 Handler.sendEmpty Message(int).또한 메시지 대상 은 수 동 으로 회수 할 수 없 음 을 주의해 야 합 니 다.즉,메시지.recycle()을 호출 하여 메시지 대상 을 방출 할 수 없습니다.이 대상 이 대기 열 에서 꺼 내 처리 되면 메시지 큐 내부 에서 자동 으로 recycle()을 할 수 있 기 때 문 입 니 다.이것 은 이해 하기 도 쉽 습 니 다.메시지 큐 에 메 시 지 를 보 낸 후에 메시지 가 언제 처 리 될 지 응용 프로그램 에 있어 서 는 모 르 고 Message Queue 만 알 수 있 기 때문에 Message Queue 에서 회수 하여 방출 하 는 동작 을 할 수 밖 에 없습니다.Handler 는 스 레 드 내부 의 메시지 대기 열 을 조작 하 는 데 사용 되 기 때문에 Handler 는 하나의 스 레 드 에 의존 해 야 하고 하나의 스 레 드 만 있 을 수 있 습 니 다.한 스 레 드 에 Handler 를 만 들 고 Handler 의 반전 handlerMessage(Message msg)를 지정 해 야 한 다 는 것 이다.Handler 는 주로 두 가지 용도 가 있 는데 하 나 는 라인 내부 메시지 순환 에 사용 된다.또 하 나 는 스 레 드 간 통신 에 사용 되 는 것 이다.Handler 의 기본 적 인 용법 은 문 서 를 참고 할 수 있 고 비교적 명확 하 게 말 할 수 있다.스 레 드 내부 메시지 순환 에 사용 되 는 것 은 주로 미래 에 특정한 동작 을 하거나 순환 적 이 고 주기 적 으로 특정한 동작 을 하 는 데 사용 된다.주요 인터페이스 는    Handler.sendEmptyMessageDelayed(int msgid, long after);    Handler.sendMessageDelayed(Message msg, long after);    Handler.postDelayed(Runnable task, long after);    Handler.sendMessageAtTime(Message msg, long timeMillis);    Handler.sendEmptyMessageAtTime(int id, long timeMiilis);    Handler.postAtTime(Runnable task, long timeMillis);이 방법 들 은 지 정 된 시간 이 지나 거나 지 정 된 시간 에 Handler 가 있 는 Message Queue 에 메 시 지 를 보 내 는 타 이 머 를 설정 하 는 것 이 목적 이다.이렇게 하면 프로그램 이 정시 작업 을 하거나 순환 순서 작업 을 하 는 데 매우 편리 하 다.이 메 시 지 를 사용 하 는 것 은 어렵 지 않 지만 주의해 야 할 것 은 스 레 드 내부 메시지 순환 은 동시 처리 가 아 닙 니 다.즉,모든 메 시 지 는 Handler 가 속 한 스 레 드 에서 처리 되 기 때문에 post(Runnable r)로 Message Queue 에 Runnable 을 보 내 지만 새로운 스 레 드 를 만 들 지 않 습 니 다.이 메 시 지 를 처리 할 때 r.run()만 호출 합 니 다.()다른 스 레 드 를 실행 하려 면 Runnable 을 Thread 에 넣 어야 합 니 다).예 를 들 어 메 인 스 레 드 가 Handler 를 통 해 백 스테이지 스 레 드 와 통신 하고 메 인 스 레 드 는 Handler 로 순환 시 서 를 실현 하 는 것 을 보 여 줍 니 다.동 영상 을 재생 합 니 다.스 레 드 는 MediaPlayer 를 만 들 고 초기 화 하 는 데 사 용 됩 니 다.초기 화 되면 메 인 스 레 드 의 Handler 를 통 해 메 인 스 레 드 를 알려 주 고 메 인 스 레 드 는 동 영상 을 재생 할 수 있 습 니 다.재생 과정 에서 sendmessageDelayed()를 통 해 재생 진도 의 끊 임 없 는 업 데 이 트 를 실현 합 니 다.

public class HandlerSimpleDemo extends Activity {
    protected static final String TAG = "HandlerSimpleDemo";
    private static final int MEDIA_PLAYER_READY = 0;
    private static final int REFRESH_PROGRESS = 1;

    private Button mStart;
    private Button mStop;
    private SurfaceHolder mSurfaceHolder;
    private ProgressBar mProgressBar;
    private SurfaceView mDisplay;
    private MediaPlayer mMediaPlayer;

    private Handler mMainHandler = new Handler() {
 @Override
 public void handleMessage(Message msg) {
     switch (msg.what) {
     case MEDIA_PLAYER_READY:
  mProgressBar.setMax(mMediaPlayer.getDuration());
  mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
      public void onCompletion(MediaPlayer mp) {
   mProgressBar.setProgress(mMediaPlayer.getDuration());
   mMainHandler.removeMessages(REFRESH_PROGRESS);
      }
  });
  mStart.setEnabled(true);
  mStop.setEnabled(true);
  break;
     case REFRESH_PROGRESS:
  int cp = mMediaPlayer.getCurrentPosition();
  mProgressBar.setProgress(cp);
  int delay = 1000 - (cp % 1000);
  mMainHandler.sendEmptyMessageDelayed(REFRESH_PROGRESS, delay);
  break;
     default:
  break;
     }
 }
    };

    @SuppressWarnings("deprecation")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.handler_simple_demo);
 mStart = (Button) findViewById(R.id.handler_simple_start);
 mStart.setOnClickListener(new View.OnClickListener() {
     public void onClick(View v) {
  mMediaPlayer.start();
  mMainHandler.sendEmptyMessage(REFRESH_PROGRESS);
     }
 });
 mStart.setEnabled(false);
 mStop = (Button) findViewById(R.id.handler_simple_stop);
 mStop.setOnClickListener(new View.OnClickListener() {
     public void onClick(View v) {
  mMainHandler.removeMessages(REFRESH_PROGRESS);
  mMediaPlayer.pause();
     }
 });
 mStop.setEnabled(false);
 mProgressBar = (ProgressBar) findViewById(R.id.handler_simple_progress);
 mDisplay = (SurfaceView) findViewById(R.id.handler_simple_display);
 mSurfaceHolder = mDisplay.getHolder();
 mSurfaceHolder.setFixedSize(mDisplay.getWidth(), mDisplay.getHeight());
 // Do not believe the document, setType is necessary, otherwise, video won't play correctly
 mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

 new Thread(new Runnable() {
     public void run() {
  try {
      mMediaPlayer = MediaPlayer.create(getApplication(), R.raw.flug);
      mMediaPlayer.setDisplay(mSurfaceHolder);
      mMainHandler.sendEmptyMessage(MEDIA_PLAYER_READY);
  } catch (IllegalArgumentException e) {
      Log.e(TAG, "caught exception e", e);
  } catch (SecurityException e) {
      Log.e(TAG, "caught exception e", e);
  } catch (IllegalStateException e) {
      Log.e(TAG, "caught exception e", e);
  }
     }
 }).start();
    }
    @Override
    protected void onDestroy() {
 super.onDestroy();
 mMainHandler.removeMessages(REFRESH_PROGRESS);
 if (mMediaPlayer != null) {
     mMediaPlayer.release();
 }
    }
}

좋은 웹페이지 즐겨찾기