Looper.getMainLooper()사용 오류

4535 단어 android
하위 스 레 드 에서 메 인 스 레 드 에 메 시 지 를 보 내 는 demo 를 실현 하고 싶 습 니 다.코드 는 다음 과 같 습 니 다.
public class HandlerActivity extends AppCompatActivity {

    private static final String TAG = "Handler";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler2);

        Handler mainHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                Log.i(TAG, "mainHandler handle message");
            }
        };


        Thread thread = new Thread(new Runnable() {
            
            @Override
            public void run() {
                Handler handler = new Handler(Looper.getMainLooper());
                Message message = Message.obtain(handler);
                message.sendToTarget();
            }
        });
        thread.start();
    }
}

실행 후 main Handler handle message 라 는 로 그 를 인쇄 하지 않 았 습 니 다.왜 일 까요?
우 리 는 Handler 의 초기 화 는 두 가지 방식 이 있 는데 하 나 는 매개 변수 가 없고 하 나 는 Looper 대상 을 전달 하 는 것 이다.
Handler handler = newHandler();

이 방식 은 현재 스 레 드 에 대응 하 는 Looper 대상 을 가 져 오고 Looper 에 대응 하 는 Message Queue 와 연 결 됩 니 다.메 인 스 레 드 에서 이 구조 방법 을 호출 한다 면 MainLooper 를 사용 합 니 다.이 Handler 의 handleMessage 방법 에 서 는 UI 를 업데이트 할 수 있 습 니 다.
또 다른 초기 화 방법 은 Looper 대상 을 전달 하 는 것 이다.
Handler handler = newHandler(looper);

위의 데모 에서 저 는 Looper.getMainLooper()로 메 인 스 레 드 에 대응 하 는 Looper 를 가 져 온 다음 에 Message.obtain(handler)을 사용 하여 sendToTarget()방법 으로 메 인 스 레 드 에 대응 하 는 Message Queue 에 메 시 지 를 보 냅 니 다.
메 시 지 는 보 냈 을 것 이지 만 main Handler 의 handle Message 는 반전 되 지 않 았 다.원본 코드 를 살 펴 보고 문제점 을 발견 했다.
Looper.loop()방법의 원본 코드 를 보십시오.
public static void loop() {
        //       ···

        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
            //       ···
            try {
                msg.target.dispatchMessage(msg); //        
                end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
            //       
    }

핵심 코드 는 바로 아래 의 이 문장 이다.
msg.target.dispatchMessage(msg);

msg.target 은 Message 초기 화 에 대응 하 는 Handler 를 말 하 는데 Handler 의 dispatchMessage 방법 을 사용 합 니 다.디 스 패 치 메시지 방법 을 다시 한 번 볼 게 요.
public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

우리 의 Demo 운행 논리 에 따 르 면 마지막 줄 인 handle Message(msg)방법 을 갔 을 것 입 니 다.이로써 진실 이 밝 혀 졌 습 니 다.결론 은 어느 핸들 러 를 통 해 정 보 를 얻 었 는 지,어느 핸들 러 안에서 되 돌 렸 다 는 것 이다.
코드 를 개조 하여 위의 결론 을 검증 하 세 요.
public class HandlerActivity extends AppCompatActivity {

    private static final String TAG = "Handler";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler2);

        Handler mainHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                Log.i(TAG, "mainHandler handle message");
            }
        };


       Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {
                Handler handler = new Handler(Looper.getMainLooper()) {
                    @Override
                    public void handleMessage(Message msg) {
                        Log.i(TAG, "threadHandler handle message");
                        Toast.makeText(HandlerActivity.this, "test", Toast.LENGTH_SHORT).show();
                    }
                };
                Message message = Message.obtain(handler);
                message.sendToTarget();
            }
        });
        thread.start();
    }
}

위의 프로그램 을 다시 실행 하면 Toast 알림 이 나타 나 고 handlerMessage 에서 UI 를 업데이트 할 수 있 습 니 다.
MainLooper 구조 Handler 를 사용 하지 않 으 면 Looper.prepare()와 Looper.loop()방법 을 사용 해 야 합 니 다.

좋은 웹페이지 즐겨찾기