Android 之 Handler

发布于:2025-08-08 ⋅ 阅读:(15) ⋅ 点赞:(0)

下面是一个使用 ​​Handler​​ 在 Android 中实现线程间通信的完整示例,涵盖 ​​后台任务执行​​、​​进度更新​​ 和 ​​UI 安全更新​​ 等场景,基于 Java 实现并适配最新实践(如 Looper.getMainLooper() 明确指定主线程)。


📱 ​​示例功能​

  1. 点击按钮启动后台耗时任务(模拟文件下载)。
  2. 后台任务通过 Handler 发送进度消息到主线程。
  3. 主线程更新进度条和文本显示。
  4. 支持取消任务。
​​完整代码​​
​​1. 布局文件 (activity_main.xml)​

<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="16dp">

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100" />

    <TextView
        android:id="@+id/tvProgress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="0%"
        android:textAlignment="center"
        android:layout_marginTop="8dp"/>

    <Button
        android:id="@+id/btnStart"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="开始下载"
        android:layout_marginTop="16dp"/>

    <Button
        android:id="@+id/btnCancel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="取消下载"
        android:layout_marginTop="8dp"/>

</LinearLayout>

​​2. Activity 代码 (MainActivity.java)​

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
    private ProgressBar progressBar;
    private TextView tvProgress;
    private Button btnStart, btnCancel;
    private Handler mainHandler; // 主线程Handler
    private volatile boolean isCancelled = false; // 任务取消标志

    // 定义消息类型常量
    private static final int MSG_UPDATE_PROGRESS = 1;
    private static final int MSG_TASK_COMPLETE = 2;

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

        progressBar = findViewById(R.id.progressBar);
        tvProgress = findViewById(R.id.tvProgress);
        btnStart = findViewById(R.id.btnStart);
        btnCancel = findViewById(R.id.btnCancel);

        // 初始化Handler,绑定主线程Looper
        mainHandler = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MSG_UPDATE_PROGRESS:
                        int progress = msg.arg1;
                        progressBar.setProgress(progress);
                        tvProgress.setText(progress + "%");
                        break;
                    case MSG_TASK_COMPLETE:
                        tvProgress.setText("下载完成!");
                        btnStart.setEnabled(true);
                        break;
                }
            }
        };

        // 开始按钮点击事件
        btnStart.setOnClickListener(v -> {
            isCancelled = false;
            btnStart.setEnabled(false);
            startDownloadTask(); // 启动后台任务
        });

        // 取消按钮点击事件
        btnCancel.setOnClickListener(v -> {
            isCancelled = true;
            btnStart.setEnabled(true);
        });
    }

    // 模拟后台下载任务
    private void startDownloadTask() {
        new Thread(() -> {
            for (int progress = 0; progress <= 100; progress++) {
                if (isCancelled) break; // 检查取消标志

                // 模拟耗时操作(如下载)
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                // 发送进度消息到主线程
                Message msg = mainHandler.obtainMessage();
                msg.what = MSG_UPDATE_PROGRESS;
                msg.arg1 = progress; // 传递进度值
                mainHandler.sendMessage(msg);
            }

            // 任务完成/取消后更新UI
            if (!isCancelled) {
                mainHandler.sendEmptyMessage(MSG_TASK_COMPLETE);
            }
        }).start();
    }
}

 ​​关键机制解析​

  1. ​主线程 Handler 初始化​

    mainHandler = new Handler(Looper.getMainLooper()) { ... }
    • 在 handleMessage() 中安全更新 UI(如进度条和文本)。
  2. ​后台线程通信​

    • 后台线程通过 mainHandler.obtainMessage() 创建消息对象,设置 what(消息类型)和 arg1(进度值)。
    • 调用 sendMessage() 将消息发送到主线程队列。
  3. ​任务取消控制​

    • volatile boolean isCancelled 确保多线程可见性。
    • 后台循环中检查标志位,及时终止任务

网站公告

今日签到

点亮在社区的每一天
去签到