Android Loop机制中Looper与handler怎么使用

发布时间:2022-11-18 09:21:52 作者:iii
来源:亿速云 阅读:153

Android Loop机制中Looper与Handler怎么使用

目录

  1. 引言
  2. Android消息机制概述
  3. Looper的工作原理
  4. Handler的工作原理
  5. Looper与Handler的协同工作
  6. Looper与Handler的使用场景
  7. Looper与Handler的常见问题与解决方案
  8. Looper与Handler的源码分析
  9. Looper与Handler的性能优化
  10. Looper与Handler的扩展应用
  11. 总结

引言

在Android开发中,消息机制是一个非常重要的概念。它允许我们在不同的线程之间进行通信,从而实现异步任务的处理。Looper和Handler是Android消息机制中的两个核心组件,它们协同工作,使得消息的发送、接收和处理变得简单而高效。

本文将深入探讨Looper和Handler的工作原理、使用方法、常见问题及其解决方案,并通过源码分析来帮助读者更好地理解它们的内部机制。此外,我们还将讨论如何优化Looper和Handler的性能,并探索它们在实际开发中的扩展应用。

Android消息机制概述

Android的消息机制主要由以下几个组件组成:

这些组件协同工作,构成了Android的消息机制。Looper和Handler是其中的核心组件,它们的关系密不可分。

Looper的工作原理

Looper的基本概念

Looper是一个消息循环器,它的主要作用是不断地从消息队列中取出消息,并将消息分发给对应的Handler处理。每个线程只能有一个Looper,但可以有多个Handler。

Looper的创建与启动

在Android中,主线程(UI线程)默认已经创建并启动了Looper。对于其他线程,如果需要使用Looper,必须手动创建并启动。

class MyThread extends Thread {
    public Handler mHandler;

    @Override
    public void run() {
        Looper.prepare(); // 创建Looper
        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                // 处理消息
            }
        };
        Looper.loop(); // 启动Looper
    }
}

Looper的退出

Looper的退出可以通过调用Looper.quit()Looper.quitSafely()方法来实现。quit()会立即退出Looper,而quitSafely()会等待所有消息处理完毕后再退出。

Looper.myLooper().quit(); // 立即退出
Looper.myLooper().quitSafely(); // 安全退出

Handler的工作原理

Handler的基本概念

Handler是消息处理器,它负责发送和处理消息。每个Handler都与一个Looper关联,Handler发送的消息会被放入Looper的消息队列中,并由Looper分发给Handler处理。

Handler的创建

Handler的创建需要与一个Looper关联。如果Handler是在主线程中创建的,那么它会自动与主线程的Looper关联。如果是在其他线程中创建的,则需要手动指定Looper。

Handler handler = new Handler(Looper.getMainLooper()); // 与主线程的Looper关联

Handler的消息发送

Handler可以通过sendMessage()post()等方法发送消息。消息可以是Message对象,也可以是Runnable对象。

Message msg = handler.obtainMessage();
msg.what = 1;
msg.obj = "Hello";
handler.sendMessage(msg);

handler.post(new Runnable() {
    @Override
    public void run() {
        // 执行任务
    }
});

Handler的消息处理

Handler通过handleMessage()方法来处理消息。开发者可以重写这个方法来实现自定义的消息处理逻辑。

Handler handler = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case 1:
                // 处理消息
                break;
            default:
                super.handleMessage(msg);
        }
    }
};

Looper与Handler的协同工作

消息的发送与处理流程

  1. 消息发送:Handler通过sendMessage()post()方法将消息发送到消息队列中。
  2. 消息入队:消息被放入与Handler关联的Looper的消息队列中。
  3. 消息循环:Looper不断从消息队列中取出消息,并分发给对应的Handler处理。
  4. 消息处理:Handler的handleMessage()方法被调用,处理消息。

Looper与Handler的关系

Looper与Handler的使用场景

主线程与子线程的通信

在Android开发中,主线程负责UI的更新,而子线程负责耗时操作。通过Looper和Handler,子线程可以将任务结果发送给主线程,主线程再更新UI。

// 子线程
new Thread(new Runnable() {
    @Override
    public void run() {
        // 执行耗时操作
        Message msg = mainHandler.obtainMessage();
        msg.what = 1;
        msg.obj = result;
        mainHandler.sendMessage(msg);
    }
}).start();

// 主线程
Handler mainHandler = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case 1:
                // 更新UI
                break;
        }
    }
};

定时任务

通过Handler的postDelayed()方法,可以实现定时任务。

Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
    @Override
    public void run() {
        // 执行任务
    }
}, 1000); // 延迟1秒执行

异步任务的处理

通过Looper和Handler,可以实现异步任务的处理。子线程执行耗时操作,主线程处理结果。

// 子线程
new Thread(new Runnable() {
    @Override
    public void run() {
        // 执行耗时操作
        Message msg = mainHandler.obtainMessage();
        msg.what = 1;
        msg.obj = result;
        mainHandler.sendMessage(msg);
    }
}).start();

// 主线程
Handler mainHandler = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case 1:
                // 处理结果
                break;
        }
    }
};

Looper与Handler的常见问题与解决方案

内存泄漏

Handler如果持有Activity的引用,可能会导致内存泄漏。解决方案是使用静态内部类或弱引用。

private static class MyHandler extends Handler {
    private final WeakReference<MyActivity> mActivity;

    MyHandler(MyActivity activity) {
        mActivity = new WeakReference<>(activity);
    }

    @Override
    public void handleMessage(Message msg) {
        MyActivity activity = mActivity.get();
        if (activity != null) {
            // 处理消息
        }
    }
}

消息队列积压

如果消息队列中的消息过多,可能会导致消息处理延迟。解决方案是合理设计消息处理逻辑,避免发送过多的消息。

线程安全问题

在多线程环境下,Handler的消息处理可能会出现线程安全问题。解决方案是使用同步机制,如synchronized关键字。

synchronized (this) {
    // 处理消息
}

Looper与Handler的源码分析

Looper的源码分析

Looper的核心代码位于android.os.Looper类中。以下是Looper的关键方法:

public static void prepare() {
    prepare(true);
}

private static void prepare(boolean quitAllowed) {
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper(quitAllowed));
}

public static void loop() {
    final Looper me = myLooper();
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    final MessageQueue queue = me.mQueue;

    for (;;) {
        Message msg = queue.next(); // 可能会阻塞
        if (msg == null) {
            return;
        }
        msg.target.dispatchMessage(msg);
        msg.recycleUnchecked();
    }
}

Handler的源码分析

Handler的核心代码位于android.os.Handler类中。以下是Handler的关键方法:

public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}

public void handleMessage(Message msg) {
    // 空实现,子类可以重写
}

Looper与Handler的性能优化

减少消息发送频率

频繁发送消息会导致消息队列积压,影响性能。可以通过合并消息或减少消息发送频率来优化。

使用Message.obtain()复用Message对象

创建Message对象时,尽量使用Message.obtain()方法,而不是直接new一个Message对象。Message.obtain()会从消息池中获取一个可复用的Message对象,减少内存分配的开销。

Message msg = Message.obtain();
msg.what = 1;
msg.obj = "Hello";
handler.sendMessage(msg);

避免在主线程中执行耗时操作

主线程的Looper负责处理UI更新,如果主线程中执行耗时操作,会导致UI卡顿。应该将耗时操作放到子线程中执行,再通过Handler将结果发送给主线程。

Looper与Handler的扩展应用

自定义Looper

在某些场景下,可能需要自定义Looper。例如,创建一个后台线程的Looper,专门用于处理某些特定的任务。

class MyLooperThread extends Thread {
    public Handler mHandler;

    @Override
    public void run() {
        Looper.prepare();
        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                // 处理消息
            }
        };
        Looper.loop();
    }
}

自定义Handler

通过继承Handler,可以实现自定义的消息处理逻辑。例如,创建一个专门处理某种类型消息的Handler。

class MyHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case 1:
                // 处理特定类型的消息
                break;
            default:
                super.handleMessage(msg);
        }
    }
}

使用HandlerThread

HandlerThread是Android提供的一个带有Looper的线程类,可以方便地创建一个带有Looper的线程。

HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper()) {
    @Override
    public void handleMessage(Message msg) {
        // 处理消息
    }
};

总结

Looper和Handler是Android消息机制中的核心组件,它们协同工作,使得消息的发送、接收和处理变得简单而高效。通过本文的介绍,相信读者已经对Looper和Handler的工作原理、使用方法、常见问题及其解决方案有了深入的了解。

在实际开发中,合理使用Looper和Handler可以大大提高应用的性能和响应速度。希望本文能够帮助读者更好地理解和应用Looper和Handler,从而开发出更加高效、稳定的Android应用。

推荐阅读:
  1. Android的Handler Looper Message机制应用实例与详解(二)
  2. Android的Handler Looper Message机制应用实例与详解(一)

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

android handler looper

上一篇:vue如何监听滚动条到底部

下一篇:React setState异步原理是什么

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》