Android Handler の post メソッドと send メソッドの違いと使い方

概要

Handler メカニズムは、Android におけるスレッド通信の一般的な方法であり、UI を更新するようにメイン スレッドに通知するサブスレッドなどのアプリケーション シナリオで使用されます。ハンドラーを使用してメッセージを送信するには、post と sendMessage の 2 つの方法があります。この記事では、主にこれら 2 つの方法の使用方法と違いについて説明します。

ハンドラーは sendMessage メソッドを使用します

sendMessage() メソッドによって渡されるパラメーターは Message オブジェクトです. ワーカー スレッドが 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 オブジェクトの run メソッドを書き換えて、UI の更新などの操作を run メソッドに入れることができます。具体的なコードは次のとおりです。

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");
                }
            });
        }
    });
}

注: Handler に対応する Looper がどのスレッドで、Runnable オブジェクトの run メソッドがどのスレッドで実行されるかを示します。例えば、上記のコードHandlerに対応するLooperはメインスレッドに配置されているので、runメソッドはメインスレッドで実行されるので、UIの更新操作はrunメソッドで行うことができます。

postメソッドとsendメソッドの違い

ハンドラーが MessageQueue からメッセージを抽出するプロセスでは、さまざまなコールバック プロセスを見ることができます。ソース コードは次のとおりです。

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 オブジェクトの callback フィールドに割り当てられ、sendMessageAtTime() メソッドによって送信されます。
メッセージを処理する場合、実際には Message オブジェクト内の Runnable オブジェクトの run メソッドを実行するための、dispatchMessage() メソッド内の handleCallback(msg) メソッドによって最初に実行されます。

(2) sendMessage などのメソッドで送信されるメッセージは、そのまま Message オブジェクトであり、メッセージを処理する場合、handleMessage(msg) メソッドを書き換えて実行される handleCallback(msg) メソッドよりも、dispatchMessage の優先度が低くなります。それ自体で。

(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) 上記のコードは、メモリ リークやその他の状況を考慮せずに、ハンドラーのデモの使用方法を示すだけのものです。送信ボタン、理論的にはすべてのクリックでボタンが新しいスレッドを作成し、スレッドプールを使用してスレッドの再利用を実現することを検討できます; (3)
send メソッドと post メソッドの両方に、sendMessageDelayed などの遅延送信メッセージを提供するカプセル化メソッドがあります。 、postDelayedなど. これらのメソッドは、インターフェースのタイミングリフレッシュなどの機能を実装するために使用されます. 興味のあるパートナーは自分で学ぶことができます~

おすすめ

転載: blog.csdn.net/weixin_46269688/article/details/124269048