安卓开发:Handler异步消息处理机制使用

在安卓开发中,直接在子线程修改UI会导致错误,必须在主线程进行。文章介绍了安卓的异步消息处理机制,包括Message、Handler、MessageQueue和Looper的角色与工作流程,并给出了示例代码,展示如何通过Handler更新UI。此外,还提到了使用Handler实现启动页延迟跳转的应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在安卓中,如果我们直接新建主线程意外的线程处理UI,是会报错的。因为安卓不能在子线程中修改UI,必须要在主线程中修改。
示例:

public void onClick(View v) {
	if(v == button) {
	    new Thread(new Runnable() {
            @Override
            public void run() {
	            textView.setText("修改之后");
            }
        }).start();
    }
}

报错的内容是:android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

很多时候,我们需要在子线程中,做耗时的操作,做完后才会有修改UI。安卓有一套异步消息处理机制,能很好的解决这个问题。
首先,新建一个activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.aiden.example.MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="修改UI" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="修改之前" />
</LinearLayout>

很简单,就是定义了一个Button和TextView。测试的方式是:通过点击Button,改变TextView的内容。
新建MainActivity.java:

import android.app.Activity;
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 Activity implements View.OnClickListener {
    private Button button;
    private TextView textView;

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

        button = (Button) this.findViewById(R.id.button);
        textView = (TextView) this.findViewById(R.id.textView);
        button.setOnClickListener(this);
    }

    private Handler handler = new Handler() {
        // 重写处理消息的方法
        public void handleMessage(Message message) {
            // 如果消息的what为1,则修改textView的内容
            if (message.what == 1) {
                textView.setText("修改之后");
            }
        }
    };

    @Override
    public void onClick(View v) {
        if (v == button) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    // 子线程sleep 3s 用于模拟耗时的操作
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    // 新建消息对象
                    Message message = new Message();
                    message.what = 1;
                    // 发送消息
                    handler.sendMessage(message);
                }
            }).start();
        }
    }
}

分析一下整个过程:
这里用到了:
1、Message:是子线程与主线程之间传递的消息。子线程通过改变what属性的值、主线程通过识别what属性的值用来识别消息。
2、Handler:通过代码可以看出,该类可以发送消息【调用sendMessage()方法】和处理消息【调用handleMessage()方法】。其中handleMessage()方法需要重写。
3、MessageQueue:看意思就知道是消息队列的意思。该队列存放所有通过Handler发送的消息。这部分消息会一直存在于消息队列中,等待被处理。这里需要注意:每个线程只有一个消息队列
4、Looper:【MessageQueue消息队列】的管家。【新建的子线程默认是不会调用loop()方法的,主线程默认会调用loop()方法】进入无线循环。若MessageQueue消息队列中存在消息,则将消息取出。交给Handler的handleMessage()方法处理该消息。这里需要注意:每个线程只有一个消息队列 该类通过调用loop()方法。

其他用法:使用Handler类实现启动页:
活动A为启动页,活动A经过3s后跳转至活动B

Handler handler = new Handler(); // 对handler进行初始化
handler.postDelayed(new Runnable() { // 实现runnable接口,将runnable对象发送给UI线程,在3s后执行该线程
	@Override
    public void run() { // 重写run方法
	    Intent intent = new Intent(活动A.this, 活动B.class);
        活动A.this.startActivity(intent);
        活动A.this.finish();
    }
}, 3000);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值