Android Handler 的用法指南

 更新时间:2025年04月03日 10:59:42   作者:沪cares  
Handler 是 Android 中用于线程间通信的重要机制,主要用于在不同线程之间发送和处理消息,下面给大家分享Android Handler 的用法指南,感兴趣的朋友一起看看吧

Android 中 Handler 的用法详解

Handler 是 Android 中用于线程间通信的重要机制,主要用于在不同线程之间发送和处理消息。以下是 Handler 的全面用法指南:

一、Handler 的基本原理

Handler 基于消息队列(MessageQueue)和循环器(Looper)工作,主要组成:

  • Message:携带数据的消息对象
  • MessageQueue:消息队列,存储待处理的消息
  • Looper:消息循环,不断从队列取出消息处理
  • Handler:发送和处理消息的接口

二、基本用法

1. 创建 Handler(主线程)

// 在主线程创建Handler会自动关联主线程的Looper
Handler mainHandler = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(Message msg) {
        // 处理消息
        switch (msg.what) {
            case 1:
                String text = (String) msg.obj;
                textView.setText(text);
                break;
        }
    }
};

2. 发送消息

// 发送空消息
handler.sendEmptyMessage(1);
// 发送带what的消息
Message msg = handler.obtainMessage();
msg.what = 2;
msg.obj = "Hello Handler";
handler.sendMessage(msg);
// 延迟发送
handler.sendEmptyMessageDelayed(1, 1000); // 1秒后发送
handler.sendMessageDelayed(msg, 2000); // 2秒后发送

3. 在子线程使用 Handler

new Thread(() -> {
    // 为当前线程创建Looper
    Looper.prepare();
    Handler threadHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // 处理子线程消息
        }
    };
    // 开始消息循环
    Looper.loop();
}).start();

三、Handler 的常见使用场景

1. 更新 UI

new Thread(() -> {
    // 模拟耗时操作
    try {
        Thread.sleep(1000);
        // 通过Handler发送消息到主线程更新UI
        Message msg = mainHandler.obtainMessage();
        msg.what = 1;
        msg.obj = "更新后的文本";
        mainHandler.sendMessage(msg);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}).start();

2. 定时任务

// 延迟执行
handler.postDelayed(() -> {
    Toast.makeText(this, "5秒后执行", Toast.LENGTH_SHORT).show();
}, 5000);
// 循环执行
final Runnable runnable = new Runnable() {
    @Override
    public void run() {
        // 执行任务
        Log.d("Handler", "每隔1秒执行");
        // 再次post实现循环
        handler.postDelayed(this, 1000);
    }
};
handler.postDelayed(runnable, 1000);
// 取消定时任务
handler.removeCallbacks(runnable);

3. 线程间通信

// 工作线程
class WorkerThread extends Thread {
    public Handler workerHandler;
    @Override
    public void run() {
        Looper.prepare();
        workerHandler = new Handler(Looper.myLooper()) {
            @Override
            public void handleMessage(Message msg) {
                // 处理来自主线程的消息
                String task = (String) msg.obj;
                Log.d("WorkerThread", "执行任务: " + task);
                // 可以回传结果给主线程
                Message resultMsg = mainHandler.obtainMessage();
                resultMsg.what = 2;
                resultMsg.obj = task + " 完成";
                mainHandler.sendMessage(resultMsg);
            }
        };
        Looper.loop();
    }
}
// 主线程发送任务给工作线程
WorkerThread worker = new WorkerThread();
worker.start();
// 等待workerHandler初始化
new Handler().postDelayed(() -> {
    if (worker.workerHandler != null) {
        Message msg = worker.workerHandler.obtainMessage();
        msg.obj = "下载文件";
        worker.workerHandler.sendMessage(msg);
    }
}, 1000);

四、高级用法

1. 使用 HandlerThread

// 创建HandlerThread
HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
handlerThread.start();
// 获取HandlerThread的Looper创建Handler
Handler threadHandler = new Handler(handlerThread.getLooper()) {
    @Override
    public void handleMessage(Message msg) {
        // 在后台线程处理消息
    }
};
// 发送消息
threadHandler.post(() -> {
    // 在HandlerThread中执行
});
// 退出时释放资源
handlerThread.quitSafely();

2. 避免内存泄漏

// 使用静态内部类+弱引用
private static class SafeHandler extends Handler {
    private final WeakReference<Activity> activityRef;
    public SafeHandler(Activity activity) {
        super(Looper.getMainLooper());
        this.activityRef = new WeakReference<>(activity);
    }
    @Override
    public void handleMessage(Message msg) {
        Activity activity = activityRef.get();
        if (activity != null && !activity.isFinishing()) {
            // 安全处理消息
        }
    }
}
// 在Activity中使用
private SafeHandler safeHandler = new SafeHandler(this);

3. 使用 Message 的优化

// 复用Message对象(推荐)
Message msg = handler.obtainMessage(WHAT_ARG, obj);
handler.sendMessage(msg);
// 设置回调代替继承Handler
handler.sendMessage(Message.obtain(handler, () -> {
    // 回调处理
}));

五、注意事项

  • 线程安全:Handler 与创建它的线程绑定,不能跨线程直接使用
  • 内存泄漏:非静态 Handler 内部类会持有外部类引用,Activity 销毁时要移除回调
  • Looper 准备:子线程使用 Handler 必须先调用 Looper.prepare()
  • 消息堆积:避免发送过多消息导致消息队列堵塞
  • 及时清理:在 onDestroy() 中移除所有回调
@Override
protected void onDestroy() {
    super.onDestroy();
    handler.removeCallbacksAndMessages(null);
    if (handlerThread != null) {
        handlerThread.quitSafely();
    }
}

到此这篇关于Android Handler 的用法详解的文章就介绍到这了,更多相关Android Handler 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Android实现手电筒电源键关闭功能

    Android实现手电筒电源键关闭功能

    这篇文章主要介绍了Android实现手电筒电源键关闭功能,在打开手电筒之后,机器休眠,客户要求点击电源键,手电筒需要关闭,下面小编给大家分享实现代码,需要的朋友可以参考下
    2017-11-11
  • Android AOP 注解详解及简单使用实例(三)

    Android AOP 注解详解及简单使用实例(三)

    这篇文章主要介绍了Android AOP 注解详解及简单使用实例(三)的相关资料,需要的朋友可以参考下
    2017-03-03
  • Android7.0中关于ContentProvider组件详解

    Android7.0中关于ContentProvider组件详解

    本文描述了Android7.0中关于ContentProvider组件实现原理以及ContentProvider发布者和调用者这两在Framework层是如何实现的。
    2017-11-11
  • Flutter利用ORM框架简化本地数据库管理详解

    Flutter利用ORM框架简化本地数据库管理详解

    使用 sqflite 相对来说还是有点复杂,比如遇到数据不兼容的时候需要手动转换,增加了不少繁琐的代码。本篇我们就来介绍一个 ORM 框架,来简化数据库的管理,感兴趣的可以了解一下
    2023-04-04
  • Android开发中CheckBox的简单用法示例

    Android开发中CheckBox的简单用法示例

    这篇文章主要介绍了Android开发中CheckBox的简单用法,结合实例形式分析了Android中CheckBox控件的基本功能设置与页面布局技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2016-07-07
  • Android开发中的ViewModel使用实战案例

    Android开发中的ViewModel使用实战案例

    在Android应用开发中,ViewModel作为架构组件,重要的功能是管理UI数据与生命周期,文章深入分析ViewModel如何感知View的生命周期,以及其核心优势,包括生命周期感知、数据持久化和与UI层解耦,帮助开发者利用ViewModel优化应用架构,需要的朋友可以参考下
    2024-10-10
  • Android超详细讲解组件ScrollView的使用

    Android超详细讲解组件ScrollView的使用

    本节带来的是Android基本UI控件中的第十个:ScrollView(滚动条),或者我们应该叫他 竖直滚动条,对应的另外一个水平方向上的滚动条:HorizontalScrollView,先让我们来了解ScrollView
    2022-03-03
  • android中Fragment+RadioButton实现底部导航栏

    android中Fragment+RadioButton实现底部导航栏

    本篇文章主要介绍了android中Fragment+RadioButton实现底部导航栏,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-03-03
  • Android开发之电话拨号器实例详解

    Android开发之电话拨号器实例详解

    这篇文章主要介绍了Android开发之电话拨号器,结合实例形式详细分析了Android电话拨号器的实现步骤与具体代码,并附带了一个Android开放电话拨号器的学习笔记,需要的朋友可以参考下
    2015-12-12
  • Android 实现不同字体颜色的TextView实现代码

    Android 实现不同字体颜色的TextView实现代码

    这篇文章主要介绍了Android 实现不同字体颜色的TextView实现代码的相关资料,需要的朋友可以参考下
    2017-05-05

最新评论