深入理解 Android Handler

Android——Handler详解 1. 简介 Handler是一套 Android 消息传递机制 可以说只要有异步线程与主线程通信的地方就一定会有 Handler。 在多线程的应用场景中,将工作线程中需更新UI的操作信息 传递到 UI主线程,从而实现 工作线程对UI的更新处理,最终实现异步消息的处理 使用Handler消息传递机制主要是为了多个线程并发更新UI的同时,保证线程安全 2. 相关概念解释 Handler、Message、Message Queue、Looper Android消息机制: 以Handler的sendMes 阅读详情

一、引言

Handler 在安卓中的地位是不言而喻的,几乎维系着整个安卓程序运行的生命周期,但是这么重要的一个东西,我们真的了解它吗?下面跟随着我的脚步,慢慢揭开Hanler的神秘面纱吧!

本文将介绍Handler 的运行机制、MessageQueue、Looper 的关系,ThreadLocal,以及Handler 导致的内存泄漏问题


二、Handler 系统组成概览

在 Handler 的源码中,主要涉及以下核心组件:

  • Message:封装消息的数据结构。
  • MessageQueue:存储 Message 的队列,内部是单链表。
  • Looper:负责循环读取 MessageQueue 并分发消息。
  • Handler:对外提供 sendMessage()、post() 发送消息,并处理 MessageQueue 中的消息。

它们之间关系如下图所示:


三、Handler 的创建

当 Handler 被创建时,它会绑定当前线程的 Looper:

public Handler() {
    this(Looper.myLooper(), null, false);
}
public Handler(Looper looper) {
    this(looper, null, false);
}

最终调用:

public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async,
               boolean shared) {
    mLooper = looper;
    mQueue = looper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
    mIsShared = shared;
}
  • mLooper 通过 Looper.myLooper() 获取当前线程的 Looper。
  • mQueue 由 Looper 提供,确保所有 Handler 在同一个 Looper 线程内共享 MessageQueue。

重点:主线程默认初始化 Looper,但子线程默认没有,需要手动 Looper.prepare()。

如果一定要在子线程中使用,推荐使用 HandlerThread,比于手动创建 Looper,HandlerThread 封装了 Looper 的创建和管理逻辑,代码更加简洁,也更易于维护。同时,HandlerThread 有自己独立的消息队列,不会干扰主线程或其他线程的消息处理。


四、sendMessage() 如何发送消息

当我们调用 sendMessage() 时:

handler.sendMessage(msg);

实际上调用:

public boolean sendMessage(Message msg) {
    return sendMessageDelayed(msg, 0);
}

最终:

public boolean sendMessageDelayed(Message msg, long delayMillis) {
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}

最终调用 enqueueMessage():

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    msg.target = this; // 绑定 Handler
    return queue.enqueueMessage(msg, uptimeMillis);
}
@UnsupportedAppUsage
/*package*/ Handler target;

也就是说 Message 引用了 Handler,这也为内存泄漏埋下伏笔


五、MessageQueue 插入消息

boolean enqueueMessage(Message msg, long when) {
    synchronized (this) {
        // 插入 MessageQueue
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }
    }
    return true;
}

enqueueMessage 方法负责将消息按照时间顺序正确地插入到单链表结构的队列中,按 when 进行排序。


六、Looper 如何处理消息

Looper.loop() 读取消息
public static void loop() {
    for (;;) {
        Message msg = queue.next(); // 取出消息
        //...
        msg.target.dispatchMessage(msg); // 交给 Handler 处理
    }
}
MessageQueue.next()
Message next() {
    // 检查消息队列是否已销毁,若销毁则返回 null
    if (mPtr == 0) return null;

    int nextPollTimeoutMillis = 0;
    for (;;) {
        // 若有超时时间,刷新 Binder 待处理命令
        if (nextPollTimeoutMillis != 0) Binder.flushPendingCommands();
        // 阻塞线程,等待新消息或超时
        nativePollOnce(mPtr, nextPollTimeoutMillis);

        synchronized (this) {
            final long now = SystemClock.uptimeMillis();
            Message msg = mMessages;
            // 若为屏障消息,找下一个异步消息
            if (msg != null && msg.target == null) {
                do { msg = msg.next; } while (msg != null && !msg.isAsynchronous());
            }
            if (msg != null) {
                // 若消息未到处理时间,计算超时时间
                if (now < msg.when) {
                    nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                } else {
                    // 若消息到处理时间,从队列移除并返回
                    mMessages = msg.next;
                    msg.next = null;
                    msg.markInUse();
                    return msg;
                }
            } else {
                // 若无消息,一直阻塞
                nextPollTimeoutMillis = -1;
            }
            // 若消息队列正在退出,释放资源并返回 null
            if (mQuitting) {
                dispose();
                return null;
            }
        }
    }
}

nativePollOnce() 让当前线程进入阻塞状态,直到有新的消息到来或者超时

nativePollOnce() 的主要功能是:

  • 线程阻塞:让当前线程进入等待状态,避免空转消耗CPU资源
  • 事件唤醒:当有新消息到达或超时发生时,立即唤醒线程处理
  • Native 层集成:与 Linux 的 epoll 机制对接,实现高效I/O多路复用
void nativePollOnce(long ptr, int timeoutMillis)

ptr:指向 Native Looper 对象的指针(C++对象地址)

timeoutMillis 的含义:

  • 如果 timeoutMillis > 0
    • epoll_wait 最多阻塞 timeoutMillis 毫秒,期间如果有事件发生,则提前返回。
  • 如果 timeoutMillis == 0
    • epoll_wait 立即返回(非阻塞)。
  • 如果 timeoutMillis < 0
    • epoll_wait 无限等待,直到有事件触发。

最终调用了 Linux epoll 机制 来监听消息事件。


七、nativePollOnce 方法调用流程

Java 层调用
// MessageQueue.java
private native void nativePollOnce(long ptr, int timeoutMillis);

JNI 本地方法,由 MessageQueue 调用,用于等待消息。

在 MessageQueue.next() 方法中:

// MessageQueue.java
nativePollOnce(mPtr, nextPollTimeoutMillis);

它的作用是:

  • 如果 MessageQueue 里有消息,立即返回。
  • 如果没有消息,则阻塞,直到有新的消息到来或 timeoutMillis 超时。
JNI 层调用
static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
        jlong ptr, jint timeoutMillis) {
    MessageQueue* mq = reinterpret_cast<MessageQueue*>(ptr);
    mq->pollOnce(timeoutMillis);
}

将 Java 传来的 mPtr 转换成 MessageQueue* 对象,并调用 pollOnce() 方法。

Native 层 pollOnce()

在 MessageQueue.cpp:

void MessageQueue::pollOnce(int timeoutMillis) {
    mLooper->pollOnce(timeoutMillis);
}

调用了 Looper::pollOnce(),进入 消息轮询 逻辑。

Looper 的 pollOnce()

在 Looper.cpp:

int Looper::pollOnce(int timeoutMillis) {
    return pollInner(timeoutMillis);
}

这里调用 pollInner(timeoutMillis),它的核心逻辑是 使用 epoll_wait() 监听事件。

epoll 监听消息事件

pollInner(timeoutMillis) 的核心逻辑:

int Looper::pollInner(int timeoutMillis) {
    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
    
    int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);

    if (eventCount > 0) {
        for (int i = 0; i < eventCount; i++) {
            // 处理事件
        }
    }
}

其中:

  • mEpollFd 是 epoll 文件描述符,用于监听多个文件描述符(FD)。
  • epoll_wait() 会 阻塞当前线程,直到:
    • 有 新消息可读
    • 有 文件描述符事件触发
    • 超时(timeoutMillis 毫秒后自动返回)

到这里,我们清楚了 nativePollOnce 的主要作用是等待新消息到达消息队列。当调用这个方法时,如果当前消息队列中没有需要立即处理的消息,线程会被阻塞,从而释放 CPU 资源,直到有新消息到来或者发生其他唤醒条件。

那么 epoll_wait() 如何监听消息?
epoll_wait() 监听哪些事件?

MessageQueue 的 pipe(管道):当 Handler 发送消息时,写入 pipe,触发 epoll 事件。

输入事件:当用户触摸屏幕或按键时,触发 epoll 事件。

文件描述符(FileDescriptor):例如 Binder 进程间通信(IPC)事件。

等等…

消息如何触发 epoll?
  • Handler.sendMessage() 会向 MessageQueue 写入数据:
void Looper::wake() {
    uint64_t inc = 1;
    ssize_t nWrite = write(mWakeEventFd, &inc, sizeof(uint64_t));
    // 错误处理省略...
}

具体调用在 MessageQueue.enqueueMessage(),会通过 nativeWake() 唤醒 Looper 的事件循环。

// MessageQueue.java
boolean enqueueMessage(Message msg, long when) {
    // ... 插入消息逻辑 ...
    if (mQuitting) {
        return false;
    }
    // 唤醒 Looper
    nativeWake(mPtr);
}

完整调用链:

Handler.sendMessage() 
→ MessageQueue.enqueueMessage() 
→ MessageQueue.nativeWake() (JNI)
→ NativeMessageQueue.wake() 
→ Looper.wake() 
→ write(mWakeEventFd, &inc, sizeof(uint64_t))
  • mWakeEventFd 是一个 eventfd 文件描述符,用于线程间唤醒(比 pipe 更高效)。
  • 写入的内容 是一个 uint64_t 的值。
  • 写入的时机 是当新消息被插入到队列头部,或队列原本为空时需要唤醒线程时。
  • epoll_wait() 监听到 pipe 有数据,返回。

  • Looper 处理新消息,Java 层 Handler 开始执行 handleMessage()。

epoll_wait阻塞等待wakeFd上的可读事件,当有数据写入wakeFd,epoll_wait返回,线程被唤醒,这里并不关心写入wakeFd的具体数据是什么,只关心可读事件的发生。

pipe 的作用

让 Handler.sendMessage() 触发 epoll 事件,立即唤醒 Looper。

至此,综上,我们可以知道 epoll_wait() 只负责等待事件,不会提前返回“第一条消息”,它只会返回“有事件触发”的信号,具体执行哪个消息是 MessageQueue.next() 的逻辑,它会选择最早应该执行的消息,这就是 Handler 的阻塞唤醒的核心逻辑所在!


八、Handler 处理消息

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

最终执行:

@Override
public void handleMessage(Message msg) {
    // 需要用户实现
}

九、核心组件之间的关系

Thread
  └── ThreadLocal<Looper>
        └── Looper
              └── MessageQueue
                    └── Message1 → Message2 → ...
                          ↑
                       Handler
  • Handler 持有对 MessageQueue 的引用(间接通过 Looper)因为Handler中的 MessageQueue 是从 Looper 中获取的;
    public Handler(@Nullable Callback callback, boolean async) {
        //..
        mQueue = mLooper.mQueue;
        //..
    }
  • 每个线程通过 ThreadLocal 绑定自己的 Looper;
  • Looper 管理其对应的 MessageQueue;

这样它们的关系就清晰了,每个线程只有一个Looper(是由ThreadLocal确保的),可以有多个Handler。

public final class Looper {
    // 线程本地存储,每个线程一个Looper实例
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

    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));
    }
}

关于ThreadLocal的详细介绍可以看这篇文章:深入剖析Java中ThreadLocal原理


十、内存泄漏问题分析及解决方案

我们都知道判断内存泄漏的依据是:短生命周期对象是否被长生命周期对象引用!既然使用Handler不当会导致内存泄漏,那么我们只需要找到被引用的源头,然后去解决。

Handler 导致内存泄漏的完整引用流程
  • 匿名内部类或非静态内部类的隐式引用:

众所周知,在Java中 匿名内部类或非静态内部类会持有外部类的引用,如下:

public class MainActivity extends AppCompatActivity {
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // 处理消息
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mHandler.sendEmptyMessageDelayed(0, 10000);
    }
}

这里的mHandler是一个非静态内部类。非静态内部类会隐式持有外部类(这里是MainActivity)的引用。这意味着mHandler对象中包含了对MainActivity实例的引用。

  • MessageQueue 对 Message 的持有:

在上面示例中,我们发送了一个延迟的Message,尽管只传了一个0,但是其内部也会封装为Message,这时候Handler 会将 Message对象并将其发送到与之关联的MessageQueue中,MessageQueue会持有这个Message对象,直到该消息被处理。

  • Message 对 Handler 的持有:

由上面第四小节的sendMessage()可知,在放入队列的时候,会将Handler 与 Message 关联:

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    msg.target = this; // 绑定 Handler
    return queue.enqueueMessage(msg, uptimeMillis);
}

主要作用是,让Message知道是从哪个Handler发送的,并最终让那个Handler 的 handleMessage去处理。

public final class Looper {
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    @UnsupportedAppUsage
    private static Looper sMainLooper;  // guarded by Looper.class
    //...
}

我们都知道,在主线程中,主线程的Looper会一直运行下去(或者说 Looper被 静态 ThreadLocal<Looper> 所引用),不能被停止,而MessageQueue 又被Looper 所引用,这就产生了一条完整的引用链:ThreadLocal<Looper> - Looper - MessageQueue - Message - Handler - MainActivity

** 解决方案**
  • 使用静态内部类 + WeakReference:

要解决内存泄漏,就是把引用链上任意一条引用断开,让GC不可达就行了,其实我们能操作的就只有 Handler - **MainActivity **这一条引用:

static class MyHandler extends Handler {
    private final WeakReference<MyActivity> ref;
    MyHandler(MyActivity activity) {
        ref = new WeakReference<>(activity);
    }

    @Override
    public void handleMessage(Message msg) {
        MyActivity activity = ref.get();
        if (activity != null) {
            // Safe to use activity
        }
    }
}
  • 在 Activity 的 onDestroy() 中清除消息:
handler.removeCallbacksAndMessages(null);

其实,只要消息不是延迟很久或者反复堆积,就不会在 MessageQueue 中长时间滞留,从而也就不会延长 Handler 或其持有对象的生命周期。

想想,在实际开发中,谁会在Activity中延迟发送一个很长时间的消息,所以我们不必为 Handler 导致内存泄漏,过度紧张,稍微留意一下就可以避免了 😃


十一、最后

Handler 是 Android 消息机制的基础组成部分。通过对 Handler、Looper、MessageQueue 之间关系的理解,我们可以更深入掌握 Android 的线程模型与 UI 更新流程。

由于本人能力有限,并没有对 Handler 进行过度深入全面了解,比如同步屏障等,如果文章内容解读有误,还望不吝赐教。

Android Handler机制使用及全面解析 仅是个人对Handler机制的理解,通过翻看源码和其他大佬对源码的阅读理解对此做了总结,文中不足的是对于nativePollOnce这个native方法做的深入了解不够多。后面如果还有其他没总结到的再写进来。 阅读详情

相关推荐

一文带你深入理解Android-Handler机制(深入至native层)

epfd 表示epoll句柄 op 表示fd操作类型,有如下3种 EPOLL_CTL_ADD 注册新的fd到epfd中 EPOLL_CTL_MOD 修改已注册的fd的监听事件 EPOLL_CTL_DEL 从epfd中删除一个fd fd 是要监听的描述符 event 表示要监听的事件,事件可以使如下如下几种宏的集合 EPOLLIN :表示对应的文件描述符可以读 EPOLLOUT:表示对应的文件描述符可以写 EPOLLERR:表示对应的文件描述符发生错误; epoll_wait .

m0_66264798的博客 1063

Android——Handler一篇就看懂

Android handler的详细讲解

未来源起的博客 9699

深入理解Android Handler机制与实践

Handler是Android中用于处理线程间通信的类,它可以发送和处理Message和Runnable对象。Handler的主要功能包括:确保Message和Runnable对象的执行被分发到创建Handler的线程中。在不同的线程中进行数据的传递。实现复杂的线程间通信逻辑。一个典型的使用场景是在非UI线程中处理耗时任务,完成后再通过Handler更新UI线程。是Handler类的核心方法,用于处理从消息队列中取出的Message对象。该方法在。

weixin_30336531的博客 1072

Android中Handler介绍

首先点击按钮会触发start函数,在start函数中创建了一个子线程,在子线程中创建消息的内容,即在getStringFromNet()中输入字符串,为了看到效果(子线程只执行run()中的代码,外面的代码都在主线程中执行),睡眠了三秒,之后使用sendMessage()将消息发送到Messagequeue中,随后主线程中使用handleMessage()去Messagequeue中取消息,最后将消息显示出来。如果队列中没有同步屏障,则返回队列中的同步消息,并将该同步消息从队列中移除。

sky_1305995351的博客 4038

VisionPro 9.0 QuickBuild里用C#脚本调用Halcon 23.11模型,保姆级图文配置流程

本文详细介绍了如何在VisionPro 9.0 QuickBuild环境中使用C#脚本调用Halcon 23.11深度学习模型,提供从环境配置到模型集成的保姆级图文教程。重点解决图像格式转换、许可证配置等工业视觉检测中的常见问题,帮助开发者快速实现高效、稳定的视觉检测流水线部署。

weixin_27027459的博客 432

自动驾驶控制算法——MPC控制算法

自动驾驶MPC控制算法摘要 模型预测控制(MPC)是一种基于系统预测模型的先进控制算法,通过滚动优化方式求解最优控制输入。其核心流程包括:1)使用数学模型预测未来系统状态;2)定义优化目标函数衡量预测误差;3)求解满足约束的最优控制序列;4)仅执行第一步控制并重复该过程。 相比传统PID控制,MPC具有预测未来、多步优化、显式处理约束等优势,特别适合自动驾驶中对安全性要求高的场景,如轨迹跟踪、车道保持、联合纵横向控制、自动泊车和动态避障等。MPC通过状态空间模型预测系统行为,在每个控制周期计算未来N步的控制

swaggytiger的博客 7919

深入理解之 Android Handler

一,相关概念 在Android中如果通过用户界面(如button)来来启动线程,然后再线程中的执行代码将状态信息输出到用户界面(如文本框),这时候就会抛出以下的异常信息: 5-12 13:33:04.393: ERROR/JavaBinder(1029):android.view.ViewRoot$CalledFromWrongThreadException:Onlythe original

紫璐宇的专栏 1万+

Foxmail 7.2.25以下版本XSS漏洞实战复现:手把手教你如何构造恶意邮件(含防御方案)

本文深入解析Foxmail 7.2.25以下版本的XSS漏洞(CNVD-2025-06036),详细展示如何构造恶意邮件进行跨站脚本攻击,并提供从客户端升级到企业级防护的多层次防御方案,帮助用户有效防范安全风险。

view3的博客 163

Handler——深入理解android消息机制

android 重要核心知识点,怎么深刻理解都不为过 常用api,主线程接收处理消息 private Handler handler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case 1 : ...

MrPeng的博客 739

【Telephony】Telephony总纲!Phone进程流程(AOSP)

整个Framework层的Telephony框架运行在一个叫做Phone(com.android.phone)的进程中。 Phone进程启动的过程中,会初始化非常多的分支功能,SIM卡流程初始化就是其中之一,所以我觉得有必要写一下Phone进程的框架

weixin_44513784的博客 1975

ESP32S3开发实战:从Vscode+IDF环境配置到OpenOCD单步调试全流程

本文详细介绍了ESP32S3开发环境的完整搭建流程,重点讲解如何在Vscode中配置ESP-IDF开发框架,并利用OpenOCD工具实现硬件单步调试。内容涵盖从环境准备、工程创建、代码烧录到高级调试技巧的全方位实战指南,旨在帮助开发者快速掌握ESP32S3的高效开发与调试方法。

weixin_29168813的博客 208

深入理解Android中的Handler机制

Handler机制在Android多线程编程中可以说是不可或缺的角色,也是必须掌握的内容,所以深入掌握并应用Handler异步处理机制在Android开发中显得特别重要。它在使用的过程中主要与Messgae、MessageQueue、和Looper这三者一起使用,实现Android的异步消息处理机制。

reakingf的博客 2万+

无人机避障——4DMmvRadar三维点云坐标转换到无人机坐标系(三)

无人机避障——4DMmvRadar三维点云坐标转换到无人机坐标系(三)

weixin_45390670的博客 1869

Android——深入理解handler机制

handler原理解析,非常详细

海晨忆的博客 3010

深入浅出块I/O子系统(四)请求处理过程

BIO请求处理的流程 函数scsi_request_fn()代码(摘自文件drivers/scsi/scsi_lib.c) (1)static void scsi_request_fn(struct request_queue *q) (2)int scsi_dispatch_cmd(struct scsi_cmnd *cmd) { host->hostt->queuecommand(host, cmd) } (3)struct sas_internal *i sas_queuec

sinat_37817094的博客 1347

电池管理系统(BMS)技术全景解析:从基础原理到智能未来

《BMS技术演进与核心功能解析》摘要: 电池管理系统(BMS)作为新能源系统的智能中枢,已从基础保护电路发展为具备预测能力的智能系统。文章系统梳理了BMS三大技术时代:1.0保护时代(1990-2000)采用硬件保护电路;2.0智能时代(2000-2020)引入SOC算法;3.0云脑时代(2020后)实现AI预测。详细解析了BMS三大核心模块:AFE感知系统(±2mV精度)、功率驱动模块(10μs级保护)和均衡技术(效率提升至85%),并对比了主动/被动均衡技术差异。同时阐释了SOC/SOH等关键参数定义与

bother3000的博客 2984

Android线程间通信机制——深入理解 Looper、Handler、Message

Android中的Looper , Handler , Message有什么关系?本篇博客目的首先为大家从源码角度介绍3者关系,然后给出一个容易记忆的结论。 1、 概述 Handler 、 Looper 、Message 这三者都与Android异步消息处理线程相关的概念。那么什么叫异步消息处理线程呢? 异步消息处理线程启动后会进入一个无限的循环体之中,每循环一次,从其内部的消息队列中取

zhangcanyan的博客 1698

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

深入理解android Handler机制

通过源码理解android 中Handler,Message,Looper,MessageQueue之间的关系,之前说到handler机制,都是在网上看到得别人是怎么讲解的,自己就机械的记下来,回来忘了再到网上搜一堆资料看看,对自己本身能力没有太大的提升。纸上得来终觉浅 绝知此事要躬行。开始试着自己阅读源码,进行深入理解一下。 首先分别介绍一些handler,message,Looper,Mess

宋大人专栏 558

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Android 深入理解Handler

&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;nbsp;Handler对于大家来说并不陌生,它对于android的消息机制来说至关重要。我们经常会通过Handler在子线程中更新UI,当然Handler不仅仅可以更新UI,还

养生阿华田 995

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

android handler 异步,深入理解Android中的Handler异步通信机制

一、问题:在Android启动后会在新进程里创建一个主线程,也叫UI线程(非线程安全)这个线程主要负责监听屏幕点击事件与界面绘制。当Application需要进行耗时操作如网络请求等,如直接在主线程进行容易发生ANR错误。所以会创建子线程来执行耗时任务,当子线程执行完毕需要通知UI线程并修改界面时,不可以直接在子线程修改UI,怎么办?解决方法:Message Queue机制可以实现子线程与UI线程...

weixin_33841242的博客 402

安卓开发21:深入理解Handler

Handler相关说明: 主要接受子线程发送的数据, 并用此数据配合主线程更新UI。 解释:安卓的UI线程(即OnCreate函数创建的线程)是线程非安全的。也就是说,在UI线程中,使用sleep这样的函数会导致整个线程延迟,但是我们在安卓开发中,往往会经常遇到一些延迟比较厉害的操作,(例如通过HTTP获取数据信息)如果放在主线程中,则会影响UI界面的渲染。但是如果另外新开一个线程,则由于UI

自娱自乐的代码人 3509

Android消息机制之Handler的深入理解

欢迎使用Markdown编辑器写博客上周老大让我主持了一个团队技术培训的会议,会议的内容是Handler技术的整体使用流程,包括从Java端到Native端的分析。借此机会,写成一篇文章记录一下成果。若有不足之处,希望大家可以指出,欢迎互相讨论,谢谢。Java层中的消息生成是从用户创建的Message对象而来的,它是一个由Runnable封装过的对象。或者从Message Pool调用getsMes

Sheldon Tse的技术博客 480
上一篇: 深入剖析Java中ThreadLocal原理
下一篇: 安卓触摸事件分发机制分析
_蓝橙
博客等级 码龄7年 1179粉丝 174原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值