IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android Handler中post方法与send方法的区别及使用 -> 正文阅读

[移动开发]Android Handler中post方法与send方法的区别及使用

概述

Handler机制是Android中线程通信的一种常用方式,应用场景如子线程通知主线程进行UI更新等。使用handler发送消息有post和sendMessage两类方法,本文主要记录这两种方法的使用以及区别。

Handler使用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();
        }
    });
}

Handler使用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方法将在主线程中执行,因此可以在run方法中进行UI更新操作。

post方法与send方法的区别

在handler从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对象中的callback字段,然后交由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>

MainActivity:

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一类方法:
send
(3)使用post一类方法:
post

后记

(1)参考博文:https://www.jianshu.com/p/2c5c4e5558f1
(2)上述代码只是为了展示如何使用Handler的Demo,没有考虑内存泄漏等情况;如send按钮中,理论上每次点击该Button都会新建一个线程,可以考虑使用线程池等实现线程复用;
(3)send一类方法与post一类方法都有提供延时发送消息的封装方法,如sendMessageDelayed、postDelayed等,这些方法可以用于实现界面的定时刷新等功能,感兴趣的伙伴可以自行了解~

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-04-22 18:47:45  更:2022-04-22 18:52:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 22:36:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码