认识Android Handler

"Android Handler" 通常指的是 Android 开发中的 Handler 类,它是 Android SDK 的一部分,用于管理消息队列和线程之间的通信。它在 Android 开发中非常有用,特别是在计划消息和可运行对象(Runnables)在未来某个时间点执行时。

Android Handler 的主要功能:

  1. 消息队列管理

    • Handler 可以将消息和可运行对象发送到消息队列中,并按照接收的顺序处理这些消息和可运行对象。
  2. 线程间通信

    • 它允许不同线程之间的通信。例如,后台线程可以使用 Handler 发送消息到 UI 线程,UI 线程接收到消息后可以相应地更新用户界面。
  3. 避免UI卡顿

    • 通过将耗时操作放到后台线程中执行,并使用 Handler 更新UI,开发者可以防止UI卡顿或变得无响应。

常用方法:

  • post(Runnable r): 将一个可运行对象发送到关联的线程中执行。
  • postDelayed(Runnable r, long delayMillis): 在指定延迟时间后执行一个可运行对象。
  • sendMessage(Message msg): 发送一个消息到关联的消息队列中。
  • removeCallbacks(Runnable r): 从消息队列中移除指定的可运行对象。

示例用法:

下面是一个简单的示例,展示如何使用 Handler 从后台线程更新UI:

java 复制代码
Handler handler = new Handler(Looper.getMainLooper());

new Thread(new Runnable() {
    @Override
    public void run() {
        // 执行一些后台工作
        String result = doBackgroundWork();
        
        // 使用handler发布一个可运行对象到主线程,更新UI
        handler.post(new Runnable() {
            @Override
            public void run() {
                // 使用后台工作的结果更新UI
                textView.setText(result);
            }
        });
    }
}).start();

在这个示例中,创建了一个新线程来执行一些后台工作,并使用 Handler 将一个可运行对象发送到主线程的消息队列中。这个可运行对象会使用后台工作的结果来更新UI。

Looper 和 MessageQueue:

  • Looper :每个线程都可以有一个 Looper,它循环处理消息队列中的消息。Handler 关联到一个特定的 Looper 及其消息队列。
  • MessageQueue:这是消息和可运行对象在被处理前存储的地方。

通过使用 HandlerLooperMessageQueue,Android 应用可以有效地管理后台任务,并确保流畅的 UI 更新。

Looper 的详细介绍

Looper 是 Android 系统中负责管理一个线程的消息循环的类。它持续从消息队列中取出消息并处理。这对于 Android 的 UI 线程尤为重要,因为它确保了事件的处理和用户界面的更新。

创建 Looper 和 Handler

通常情况下,Android 的主线程(UI线程)已经有一个默认的 Looper。但对于其他需要处理消息的线程,我们必须手动创建 Looper 和 Handler。

java 复制代码
class MyThread extends Thread {
    public Handler mHandler;

    @Override
    public void run() {
        // 为当前线程准备 Looper
        Looper.prepare();

        // 创建 Handler 与当前线程的 Looper 关联
        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                // 处理消息
            }
        };

        // 启动 Looper 以处理消息队列中的消息
        Looper.loop();
    }
}

在这个例子中,我们创建了一个自定义的线程类 MyThread。在 run() 方法中,我们调用 Looper.prepare() 来初始化当前线程的 Looper,然后创建一个与该 Looper 关联的 Handler。最后,调用 Looper.loop() 开始处理消息队列中的消息。

MessageQueue 详解

MessageQueue 是一个队列,用于存储线程的消息和 Runnable 对象。它是由 Looper 管理的,Looper 从这个队列中取出消息,并通过 Handler 传递给应用程序处理。

常见的 Handler 使用场景

  1. 延迟执行任务 :使用 postDelayed(Runnable r, long delayMillis) 方法,可以在指定的时间后执行任务。

  2. 定时任务 :可以使用 Handler 实现定时任务,通过循环发送延迟消息来达到定时执行的效果。

  3. 后台线程更新 UI :在 Android 开发中,通常需要在后台线程执行耗时操作,然后在主线程更新 UI。通过 Handler,可以安全地从非 UI 线程向 UI 线程发送消息。

示例:定时任务

下面的例子展示了如何使用 Handler 实现定时任务,每隔一秒更新一次计时器:

java 复制代码
private int seconds = 0;
private boolean running = false;
private Handler handler = new Handler();

private void startTimer() {
    running = true;
    handler.post(new Runnable() {
        @Override
        public void run() {
            if (running) {
                seconds++;
                // 更新UI
                textView.setText("Seconds: " + seconds);
                // 延迟1秒再次执行
                handler.postDelayed(this, 1000);
            }
        }
    });
}

private void stopTimer() {
    running = false;
    handler.removeCallbacksAndMessages(null); // 移除所有回调和消息
}

在这个例子中,startTimer() 方法启动计时器,每秒增加一次计时器的秒数并更新 UI。stopTimer() 方法停止计时器并移除所有的回调和消息。

注意事项

  1. 避免内存泄漏 :使用 Handler 时要注意避免内存泄漏,特别是在长时间运行的任务中。尽量使用静态内部类或弱引用(WeakReference)来持有 Handler,避免持有外部类的强引用。

  2. 正确管理线程:确保正确地管理线程生命周期,避免未关闭的 Looper 导致的资源泄漏。

通过合理使用 HandlerLooperMessageQueue,开发者可以有效地处理后台任务和线程间通信,确保应用程序的响应性和流畅的用户体验。

Handler与Binder

HandlerBinder 是 Android 系统中用于不同目的的两个重要组件。

Handler

概述

Handler 主要用于在不同线程之间传递消息和执行代码。它帮助管理线程的消息队列,可以在后台线程执行耗时任务后,切换到主线程更新 UI。

关键功能
  • 消息传递 :通过发送和处理 Message 对象,在不同线程之间传递数据。
  • 任务调度 :通过 post(Runnable r)postDelayed(Runnable r, long delayMillis) 方法,调度任务在特定时间执行。
  • 线程间通信Handler 可以附加到一个线程的 Looper,从而允许跨线程通信。
使用场景
  • 更新 UI:从后台线程切换到主线程,更新 UI。
  • 延迟任务:在指定时间后执行某些操作。
  • 定时任务:以固定的间隔时间执行任务。

Binder

概述

Binder 是 Android 中的一种 IPC(进程间通信)机制,用于在不同的应用程序或系统服务之间传递数据。它是 Android 系统的基础,很多系统服务的通信都是基于 Binder 机制。

关键功能
  • 进程间通信:允许一个应用程序或服务与另一个应用程序或服务通信,即使它们在不同的进程中。
  • 传递复杂数据:可以传递复杂的对象,而不仅仅是简单的数据类型。
  • 远程方法调用:允许一个进程调用另一个进程中的方法,这个过程对调用者来说是透明的。
使用场景
  • 系统服务通信:例如,应用程序可以通过 Binder 与系统服务(如 ActivityManagerWindowManager 等)通信。
  • 应用间通信:例如,一个应用程序可以通过 Binder 机制与另一个应用程序提供的服务进行通信。
实现方式
  • AIDL(Android Interface Definition Language) :AIDL 是定义 Binder 接口的一种语言,帮助生成用于 IPC 的代码。开发者定义接口,Android 系统会生成相应的 StubProxy 类来处理 IPC。

示例:创建一个远程服务

  1. 定义 AIDL 接口

    aidl 复制代码
    // IMyAidlInterface.aidl
    interface IMyAidlInterface {
        void performAction();
        int getResult();
    }
  2. 实现 AIDL 接口

    java 复制代码
    public class MyService extends Service {
        private final IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {
            @Override
            public void performAction() {
                // 执行操作
            }
    
            @Override
            public int getResult() {
                return 42; // 返回结果
            }
        };
    
        @Override
        public IBinder onBind(Intent intent) {
            return mBinder;
        }
    }
  3. 客户端绑定服务

    java 复制代码
    ServiceConnection connection = new ServiceConnection() {
        IMyAidlInterface myAidlInterface;
    
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            myAidlInterface = IMyAidlInterface.Stub.asInterface(service);
            try {
                myAidlInterface.performAction();
                int result = myAidlInterface.getResult();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void onServiceDisconnected(ComponentName name) {
            myAidlInterface = null;
        }
    };
    
    Intent intent = new Intent(this, MyService.class);
    bindService(intent, connection, Context.BIND_AUTO_CREATE);

总结

  • Handler 用于线程间的轻量级通信和任务调度,适用于同一进程内的操作,特别是在 UI 线程和后台线程之间的交互。
  • Binder 是一种强大的进程间通信机制,允许在不同进程的应用程序或服务之间传递数据和调用方法。它在 Android 系统中被广泛用于实现应用和系统服务的通信。

HandlerBinder 在 Android 系统中有着不同的应用场景和用途,分别解决了线程内和进程间的通信问题。

相关推荐
Yawesh_best1 小时前
MySQL(5)【数据类型 —— 字符串类型】
android·mysql·adb
曾经的三心草3 小时前
Mysql之约束与事件
android·数据库·mysql·事件·约束
guoruijun_2012_47 小时前
fastadmin多个表crud连表操作步骤
android·java·开发语言
Winston Wood7 小时前
一文了解Android中的AudioFlinger
android·音频
B.-9 小时前
Flutter 应用在真机上调试的流程
android·flutter·ios·xcode·android-studio
有趣的杰克9 小时前
Flutter【04】高性能表单架构设计
android·flutter·dart
大耳猫14 小时前
主动测量View的宽高
android·ui
帅次17 小时前
Android CoordinatorLayout:打造高效交互界面的利器
android·gradle·android studio·rxjava·android jetpack·androidx·appcompat
枯骨成佛18 小时前
Android中Crash Debug技巧
android
kim56591 天前
android studio 更改gradle版本方法(备忘)
android·ide·gradle·android studio