目录
11.Handler消息处理(一)
1.Handler消息传递机制
在Java中,对于一些周期性的或者是耗时的操作通常由多线程来实现,而在Android中,也可以使用Java中的多线程技术。例如,在手机淘宝主界面的上方,对广告进行轮换显示,以及某些游戏中的计时进度条,都应用了多线程技术。
在Android中使用多线程,有一点需要注意:不能在子线程中动态改变主线程中的UI组件的属性。
注:当一个程序第一次启动时,Android会启动一条主线程,用于负责接收用户的输入,将运行的结果反馈给用户,也称为UI线程;而子线程是指为了执行一些可能产生阻塞操作而新启动的线程,也称为Worker线程。
例如,实现单击按钮时创建新线程,用于改变文本框的显示文本,代码如下:
public class MainActivity extends AppCompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView=findViewById(R.id.main_tv1);
Button button=findViewById(R.id.main_btn1);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//创建新线程
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
//要执行的操作
textView.setText("你今天的努力,是幸运的伏笔;当下的付出,是明日的花开");
}
});
thread.start();//开启线程
}
});
}
点击按钮后软件将停止运行,在Logcat面板中输出如图所示的异常信息。

原因:子线程不允许操作主线程中的组件!
为此,Android中引入了Handler消息传递机制,来实现在新创建的线程中操作UI界面。
更改后成功运行:
package com.example.demo;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
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 {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar=getSupportActionBar();
actionBar.hide();
TextView textView=findViewById(R.id.main_tv1);
Button button=findViewById(R.id.main_btn1);
Handler handler=new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
if(msg.what==0x123){
textView.setText("你今天的努力,是幸运的伏笔;当下的付出,是明日的花开");
}
}
};
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//创建新线程
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
//发送空消息
//what->指定消息代码,自定义就行
handler.sendEmptyMessage(0x123);
}
});
thread.start();
}
});
}
}
注:
进程:一个Android应用就是一个进程,每个应用在各自的进程中运行。
线程:比进程更小的独立运行的基本单位,一个进程可以包含多个线程。
1-1.Handler 类简介
Handler是Android提供的一个用来更新UI的机制,也是一个消息处理的机制。通过Handler类(消息处理类)可以发送和处理Message对象到其所在线程的MessageQueue中。
Handler类主要有以下两个作用。
(1)在任意线程中发送消息
将Message应用sendMessage() 方法发送到MessageQueue中,在发送时可以指定延迟时间、发送时间以及要携带的Bundle数据。当Looper循环到该Message时,调用相应的Handler对象的handlerMessage()方法对其进行处理。
(2)在主线程中获取并处理消息
为了让主线程能在适当的时候处理Handler所发送的消息,必须通过回调方法来实现。开发者只需要重写Handler类中处理消息的方法。这样当新启动的线程发送消息时,Handler 类中处理消息的方法就会被自动回调。
1-2.Handler 类中的常用方法
在Handler类中包含了一些用于发送和处理消息的常用方法,这些方法如表11.1 所示。
表11.1 Handler 类提供的常用方法
| 方法 | 描述 |
|---|---|
| handleMessage(Message msg) | 处理消息的方法。通常重写该方法来处理消息,在发送消息时,该方法会自动回调 |
| hasMessages(int what) | 检查消息队列中是否包含what属性为指定值的消息 |
| hasMessages(int what, Object object) | 检查消息队列中是否包含what属性为指定值且object属性为指定对象的消息 |
| post(Runnable r) | 立即发送Runnable对象,该Runnable对象最后将被封装成Message对象 |
| postAtTime(Runnable r, long uptimeMillis) | 定时发送Runnable 对象,该Runnable对象最后将被封装成Message对象 |
| postDelayed(Runnable r, long delayMillis) | 延迟发送Runnable对象,该Runnable对象最后将被封装成Message对象 |
| sendEmptyMessage(int what) | 发送空消息 |
| sendEmptyMessageDelayed(int what, long delayMillis) | 指定多少毫秒之后发送空消息 |
| sendMessage(Message msg) | 立即发送消息 |
| sendMessageAtTime(Message msg, long uptimeMillis) | 定时发送消息 |
| sendMessageDelayed(Message msg, long delayMillis) | 延迟发送消息 |
| obtainMessage() | 获取消息 |
通过这些方法,应用程序就可以方便地使用Handler来进行消息传递。
例:

MainActivity.java
package com.example.timeprogressbar;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.ProgressBar;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private ProgressBar timer;//声明水平进度条
final int TIME = 60;//定义时间长度60秒
private int mProgressStatus = 0;//定义完成的进度
final int TIMER_MSG = 0x001;//消息代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar = getSupportActionBar();
actionBar.hide();
timer = findViewById(R.id.main_pb1);
//启动进度条
handler.sendEmptyMessage(TIMER_MSG);
}
//创建Handler对象,实现1秒钟更新一次进度
Handler handler = new Handler() {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
if (TIME - mProgressStatus > 0) {//当前进度大于0
mProgressStatus++;//进度加1
timer.setProgress(TIME - mProgressStatus);//更新进度
//一秒后发送消息
handler.sendEmptyMessageDelayed(TIMER_MSG, 1000);
} else {
Toast.makeText(MainActivity.this, "时间到,游戏结束!", Toast.LENGTH_SHORT).show();
}
}
};
}
本文介绍了Android中Handler消息传递机制的重要性,强调了不能在子线程直接修改UI组件的规则,并详细阐述了Handler类的功能,包括在任意线程发送消息和在主线程处理消息的能力。同时,列举了Handler类的主要方法,帮助开发者更好地利用Handler进行消息操作。
&spm=1001.2101.3001.5002&articleId=125843979&d=1&t=3&u=692bd794e2ff471b9ce00694eb52be86)
1071

被折叠的 条评论
为什么被折叠?



