Android Handler에서 post 방식과 send 방식의 차이점과 용도

개요

핸들러 메커니즘은 Android에서 스레드 통신의 일반적인 방법으로 메인 스레드에 UI 업데이트를 알리는 하위 스레드와 같은 애플리케이션 시나리오에서 사용됩니다. 핸들러를 사용하여 메시지를 보내는 방법에는 post와 sendMessage의 두 가지 방법이 있는데, 이 글에서는 주로 이 두 가지 방법의 용도와 차이점을 기록한다.

핸들러는 sendMessage 메소드를 사용합니다.

sendMessage() 메소드가 전달하는 매개변수는 Message 객체이며, Worker 쓰레드가 Message 객체를 전달한 후 Handler의 handleMessage 메소드를 메인 쓰레드에서 재작성하여 UI 업데이트 등의 기능을 구현하는데 다음과 같다. 암호:

private Handler handlerSend = new Handler(){
    
    
    @Override
    public void handleMessage(@NonNull Message msg) {
    
    
        // 使用send方法更新UI的方式:
        // 重写handleMessage方法,在该方法内更新UI
        super.handleMessage(msg);
        if (msg.what == 1) {
    
    
            mTvTxt.setText("使用send方法更新UI");
        }
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    
    
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initBind();
    // 模拟send方法更新UI的操作
    mBtnSend.setOnClickListener(new View.OnClickListener() {
    
    
        @Override
        public void onClick(View view) {
    
    
            Thread thread = new Thread(new Runnable() {
    
    
                @Override
                public void run() {
    
    
                    handlerSend.sendEmptyMessage(1);
                }
            });
            thread.start();
        }
    });
}

핸들러는 post 메소드를 사용합니다.

post() 메소드에 의해 전달된 매개변수는 Runnable 객체입니다. 작업자 스레드에서 Runnable 개체의 실행 메서드를 다시 작성하고 UI 업데이트와 같은 작업을 실행 메서드에 넣을 수 있습니다.구체적인 코드는 다음과 같습니다.

private Handler handlerPost = new Handler();

@Override
protected void onCreate(Bundle savedInstanceState) {
    
    
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initBind();
    // 模拟post方法更新UI的操作
    mBtnPost.setOnClickListener(new View.OnClickListener() {
    
    
        @Override
        public void onClick(View view) {
    
    
            handlerPost.post(new Runnable() {
    
    
                @Override
                public void run() {
    
    
                    mTvTxt.setText("使用post方法更新UI");
                }
            });
        }
    });
}

참고: Thread가 Handler에 해당하는 Looper인 곳에서는 Runnable 객체의 run 메서드가 실행됩니다. 예를 들어, 위의 코드 Handler에 해당하는 Looper는 메인 스레드에 위치하므로 메인 스레드에서 run 메서드가 실행되므로 run 메서드에서 UI 업데이트 작업을 수행할 수 있습니다.

post 방식과 send 방식의 차이점

핸들러가 MessageQueue에서 Message를 추출하는 과정에서 다양한 콜백 프로세스를 볼 수 있으며 소스 코드는 다음과 같습니다.

public void dispatchMessage(Message msg){
    
    
  //如果是post,callback不为空,直接进入handleCallback
  if(msg.callback != null){
    
    
    handleCallback(msg);
    }else{
    
    
      //如果是sendMessage,且创建handler时没有传入callback,则callback为空,直接进入handleMessage,也就是我们自己复写的处理Message的方法
      if(mCallback !=null){
    
    
        if(mCallback.handleMessage(msg)){
    
    
          return;
        }
      }
    handleMessage(msg);
    }
}
//直接run并不会启动新线程,所以这就是post的runnable里面可以直接更新UI的原因
private static void handleCallback(Message msg){
    
    
  msg.callback.run();
  }

(1) post 메소드는 Runnable 객체를 전송하지만 결국 Message 객체로 캡슐화되며 Runnable 객체는 Message 객체의 콜백 필드에 할당된 후 sendMessageAtTime() 메소드에 의해 전송됩니다.
메시지를 처리할 때 dispatchMessage() 메서드의 handleCallback(msg) 메서드에 의해 먼저 실행되는데, 이는 실제로 Message 객체의 Runnable 객체의 run 메서드를 실행하는 것입니다.

(2) sendMessage와 같은 메소드에 의해 전송된 메시지는 바로 Message 객체이며, 메시지를 처리할 때 dispatchMessage의 우선 순위는 handleCallback(msg) 메소드의 우선 순위보다 낮으며 handleMessage(msg) 메소드를 다시 작성하여 실행됩니다. 그 자체로.

(3) post 방식과 send 방식은 본질적으로 차이가 없는 것을 알 수 있지만, 사용 방법에는 약간의 차이가 있음을 알 수 있습니다.

모든 코드

레이아웃 파일:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="20dp"
    >

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Send"
        android:textAllCaps="false"
        android:id="@+id/btn_send"
        />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Post"
        android:textAllCaps="false"
        android:id="@+id/btn_post"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="初始化状态"
        android:textSize="24sp"
        android:textColor="@color/black"
        android:id="@+id/tv_txt"
        />

</LinearLayout>

주요 활동:

package com.example.handlerdemo;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    
    

    private Button mBtnSend, mBtnPost;
    private TextView mTvTxt;

    private Handler handlerSend = new Handler(){
    
    
        @Override
        public void handleMessage(@NonNull Message msg) {
    
    
            // 使用send方法更新UI的方式:
            // 重写handleMessage方法,在该方法内更新UI
            super.handleMessage(msg);
            if (msg.what == 1) {
    
    
                mTvTxt.setText("使用send方法更新UI");
            }
        }
    };

    private Handler handlerPost = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initBind();
        // 模拟send方法更新UI的操作
        mBtnSend.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View view) {
    
    
                Thread thread = new Thread(new Runnable() {
    
    
                    @Override
                    public void run() {
    
    
                        handlerSend.sendEmptyMessage(1);
                    }
                });
                thread.start();
            }
        });
        // 模拟post方法更新UI的操作
        mBtnPost.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View view) {
    
    
                handlerPost.post(new Runnable() {
    
    
                    @Override
                    public void run() {
    
    
                        mTvTxt.setText("使用post方法更新UI");
                    }
                });
            }
        });
    }

    /**
     * 绑定UI控件
     * */
    private void initBind() {
    
    
        mBtnSend = findViewById(R.id.btn_send);
        mBtnPost = findViewById(R.id.btn_post);
        mTvTxt = findViewById(R.id.tv_txt);
    }
}

렌더링

(1) 초기 인터페이스:
초기화 인터페이스
(2) send 방법 사용:
보내다
(3) post 방법 사용:
우편

추신

(1) 참조 블로그 게시물: https://www.jianshu.com/p/2c5c4e5558f1
(2) 위의 코드는 메모리 누수 및 기타 상황을 고려하지 않고 핸들러 데모를 사용하는 방법을 보여주기 위한 것입니다. 보내기 버튼, 이론적으로 버튼을 클릭할 때마다 새 스레드가 생성되며 스레드 풀을 사용하여
스레드 재사용을 달성하는 것을 고려할 수 있습니다. , postDelayed 등 이러한 방법은 인터페이스의 타이밍 새로 고침과 같은 기능을 구현하는 데 사용됩니다.관심있는 파트너는 스스로 배울 수 있습니다 ~

추천

출처blog.csdn.net/weixin_46269688/article/details/124269048