Handler的用法和源码进行拆解,赶紧来瞧一瞧

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

Handler是什么

Handler主要用于异步消息的处理:当发出一个消息之后,首先进入一个消息队列,发送消息的函数即刻返回,而另外一个部分在消息队列中逐一将消息取出,然后对消息进行处理,也就是发送消息和接收消息不是同步的处理。这种机制通常用来处理相对耗时比较长的操作。

Handler怎么用

   public class HandlerActivity extends AppCompatActivity {
    private static final String TAG = "HandlerActivity";
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        testSendMessage();
    }

    public void testSendMessage() {
         Handler handler = new MyHandler(this);
         Message message = Message.obtain();
         message.obj = "test handler send message";
         handler.sendMessage(message);
    }

    //注1: 为什么要用静态内部???
    static class MyHandler extends Handler {
        WeakReference<AppCompatActivity> activityWeakReference; // 注2:为何要用弱引用???
        public MyHandler(AppCompatActivity activity) {
            activityWeakReference = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            Log.d(TAG, (String) msg.obj);
        }
    }
}
复制代码

Handler源码怎么解读

从使用方式的场景,咱们一步一步的探究里面是怎么实现的,还有上面的标注的两点,在后面我都会介绍的,各位客官听我慢慢道来。first,看下四大金刚关系图,文字表述再多,不如一张图来的直接。

通过上图就可以简单看出Handler、MessageQueue、Message、Looper 这四者是怎么样互相持有对方的,大概可以了解消息的传递。next,我们先来一张时序图,看下消息是怎么一步步发送出来的。

  1. 进入的是Handler.sendMessage方法。
public final boolean sendMessage(@NonNull Message msg) {
    return sendMessageDelayed(msg, 0);
}

复制代码
  1. 接下来继续调用Handler.sendMessageDelayed方法。
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
    if (delayMillis < 0) {
        delayMillis = 0;
    }
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
复制代码
  1. 接着走Handler.sendMessageAtTime 方法,这里面就要用到MessageQueue 对象了,此处说明一下,这个mQueue  是在哪里获取到的,是在Handler 构造方法里。此处贴图,从图中可以看出mLooper=Looper.myLooper() mQueue=mLooper.mQueue。Handler 中的MessageQueue是Looper中持有的MessageQueue对象 。

注1:为啥要用静态内部类----> 如果我们使用Handler 类,没有用static 关键字修饰的话,则会输出Log:The following Handler class should be static or leaks might occur。会提示你可能会引起内存泄漏。因此在注1处我用了static修饰。

public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
    MessageQueue queue = mQueue;
    if (queue == null) {
        RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue");
        Log.w("Looper", e.getMessage(), e);
        return false;
    }
    return enqueueMessage(queue, msg, uptimeMillis);
}
复制代码
  1. 接着时序图上的流程走,此时要进入到MessageQueue.enqueueMessage 方法中,该方法就是将msg对象存入到MessageQueue队列中,注意此处,将该handler对象赋值给了msg.target,这个后面会用到的,很关键。
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
        long uptimeMillis) {
    msg.target = this;
    msg.workSourceUid = ThreadLocalWorkSource.getUid();

    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    return queue.enqueueMessage(msg, uptimeMillis); //3,即将进入MessageQueue.enqueueMessage 方法。
}

复制代码
  1. 接着来看MessageQueue.enqueueMessage方法,该方法就是按照时间的顺序插入到Message这个链表结构的数据对象中去。
boolean enqueueMessage(Message msg, long when) {
    if (msg.target == null) { //4. 后面说明,这个也就是四大金刚图里的msg.target 所持有的Handler 对象。
        throw new IllegalArgumentException("Message must have a target.");
    }

    synchronized (this) {
        ...
        msg.markInUse();
        msg.when = when;
        Message p = mMessages;
        boolean needWake;
        if (p == null || when == 0 || when < p.when) {
            // New head, wake up the event queue if blocked.
            msg.next = p;
            mMessages = msg;
            needWake = mBlocked;
        } else {
            // 链表的插入操作,不太熟悉的可以看看数据结构。(此处是根据时间来排序的)
            needWake = mBlocked && p.target == null && msg.isAsynchronous();
            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;
        }

        // We can assume mPtr != 0 because mQuitting is false.
        if (needWake) {
            nativeWake(mPtr); //画重点,此处唤醒等待的next 方法。
        }
    }
    return true;
}
复制代码

此时,一条消息就相当于入队了。MessageQueue从名称来看是队列,实际上,使用的还是Message.next指针来进行操作的,也即是链表的操作。消息的入队完成,后面将会介绍该消息是怎么发送出去的。6. Loop.loop方法,敲重点。省略了部分代码,只关注核心代码。这里用到了死循环,不停的获取Message对象,获取到之后直接调用Message.target变量所持有的Handler对象,然后调用Handler.dispatchMessage方法,这样就完成了消息的分发。

public static void loop() {
    final Looper me = myLooper();
    ...
    final MessageQueue queue = me.mQueue;
    ...
    for (;;) {
        Message msg = queue.next(); // might block   //7.通过MessageQueue.next()方法获取Message对象。
        ...
        final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
        final long end;
        try {
            msg.target.dispatchMessage(msg);
            end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
        } finally {
            if (traceTag != 0) {
                Trace.traceEnd(traceTag);
            }
        }
        ...
        msg.recycleUnchecked();
    }
}
复制代码

7-8. MessageQueue.next()方法获取Message对象。

Message next() {
    ...
    int pendingIdleHandlerCount = -1; // -1 only during first iteration
    int nextPollTimeoutMillis = 0;
    for (;;) { //死循环
        if (nextPollTimeoutMillis != 0) {
            Binder.flushPendingCommands();
        }

        nativePollOnce(ptr, nextPollTimeoutMillis);   // 5: 避免了阻塞的关键点,释放资源,处于等待。疑点:处于等待,肯定需要一个东西来唤醒它。上面第5步分析enqueueMessage的时候有行代码if (needWake) {
            nativeWake(mPtr); //画重点,此处唤醒等待的next 方法。
        } 。

        synchronized (this) {
            // Try to retrieve the next message.  Return if found.
            final long now = SystemClock.uptimeMillis();
            Message prevMsg = null;
            Message msg = mMessages;
            if (msg != null && msg.target == null) { //******此条件可以先不看,因为通过Handler 发送的消息target 都会持有Handler,该逻辑不会触发。消息同步屏障的时候会优先触发该逻辑。
                // Stalled by a barrier.  Find the next asynchronous message in the queue.
                do {
                    prevMsg = msg;
                    msg = msg.next;
                } while (msg != null && !msg.isAsynchronous());
            }
            if (msg != null) { //查找当前的msg 对象。
                if (now < msg.when) {
                    // Next message is not ready.  Set a timeout to wake up when it is ready.
                    nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                } else {
                    // Got a message.
                    mBlocked = false;
                    if (prevMsg != null) {
                        prevMsg.next = msg.next;
                    } else {
                        mMessages = msg.next;
                    }
                    msg.next = null;
                    if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                    msg.markInUse();
                    return msg;
                }
            } else {
                // No more messages.
                nextPollTimeoutMillis = -1;
            }
         ...
        nextPollTimeoutMillis = 0;
    }
}
复制代码

9.Handler.dispatchMessage方法,此处有判断,如果在Activity中使用view.post方法调用的时候,就会走到handleCallback回调中。通过sendMessagexxx函数发送消息的就会走到handleMessage回调中去。

/**
 * Handle system messages here.
 */
public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}
复制代码

该方法会会将msg对象发送到客户端定义Handler的地方,重写的handleMessage方法。至此,Handler发送消息的流程大致介绍完成。

总结

Handler 发送消息的时候,在Handler.enqueueMessage方法中,将该Handler对象添加到Message中的target属性中,这样就完成了Message持有Handler的操作,为最后Message.target.dispatchMessage做了保证。然后将该Message对象放入到MessageQueue中的Message.next中去,完成了消息链表的添加;而这个MessageQueue是Looper中所持有的对象,这样就可以通过Looper类通过对MessageQueue.next()---->Message.next()--->Message.target.dispatchMessage(msg)完成了消息的分发。

补充点

Looper对象是怎么new出来的?

上图看出是在应用程序进程的ActivityThread类中的main()函数中调用了Looper.prepareMainLooper()方法,就new出来了主线程中的Looper。

上图也看出,这个Looper.prepareMainLooper()方法是系统调用的,开发者不能再次调用了,否则会抛出异常。

prepare这个方法真正的new Looper了。接着来看看Looper的构造函数。

此处创建了MessageQueue,Handler中的MessageQueue就是这块创建的。

为什么将Looper保存在ThreadLocal中?

ThreadLocal:线程的变量副本,每个线程隔离。我的理解就是,ThreadLocal内部使用了当前线程为Key,需要存储的对象为Value,通过字典保存起来的,这样客户端在获取的时候,当前线程就只会获取一份保存的Value。回到Looper中,就可以知道一个线程里按理说就会只有一个Looper。

Message 为什么推荐使用obtain()方式获取Message对象,而不推荐使用new Message()?

这里涉及到池的技术的应用:Message中维护了一个消息池,消息使用完就会回收。减少对象创建和销毁的开销;java当中的线程池也是用到了该思想。

同步屏障

同步屏障机制的作用,是让这个绘制消息得以越过其他的消息,优先被执行。系统中UI绘制会使用到同步屏障,开发中基本用不到。核心代码是先设置一个target=null的消息,插入到消息链表的头部。

然后在MessageQueue.next中优先查找同步屏障中的消息asyncHronous设置为true的异步消息。

Handler为什么会导致内存泄漏以及解决方案?

Handler导致内存泄漏一般发生在发送延迟消息的时候,当Activity关闭之后,延迟消息还没发出,那么主线程中的MessageQueue就会持有这个消息的引用,而这个消息是持有Handler的引用,而handler作为匿名内部类持有了Activity的引用,所以就有了以下的一条引用链。解决

  1. 使用静态内部类,如果要调用Activity中的方法,就可以在静态内部类中设置一个WeakReference activityWeakReference引用。
  2. 在Activity销毁的时候,即onDestory()方法中调用handler.removeCallbacks,移除runnable。



 

Android面试备战:JVM与Handler机制深度解析 在Android开发中,JVM内存模型和Handler机制是面试中的高频考点。JVM作为Java程序的运行环境,其内存分配、垃圾回收机制直接影响应用性能;而Handler作为Android线程间通信的核心组件,涉及消息队列、Looper等关键概念。理解这些底层原理不仅能优化应用性能,还能有效避免内存泄漏等问题。实际工程中,Handler机制广泛应用于UI更新、任务调度等场景,而JVM调优则是解决OOM、卡顿等问题的关键。本文通过Handler内存泄漏案例和JVM内存分析工具的使用,帮助开发者系统掌握这些核心 阅读详情

相关推荐

Android Handler 机制从底层原理到实战应用的深度彻底解析

本文深入解析Android的Handler机制,包括其核心组成、执行流程和底层原理。Handler是Android进程内线程间通信的核心机制,由Looper、MessageQueue、Handler和Message四大组件构成,实现线程间任务调度和UI更新。主线程的Looper由系统自动创建,子线程需手动调用Looper.prepare()和loop()。文章详细分析了消息发送、入队、循环和处理的全流程,解释了Looper.loop()死循环不会阻塞主线程的原因(基于Linux管道+epoll机制)。同时探

fuge2008的博客 1427

Handler使用方法详解(含实例)

0、目录 一、相关概念简介 二、使用方式 三、使用步骤 四、实例讲解 五、总结 一、相关概念简介 Handler是一套消息传递机制,通常的作用是在多线程的应用场景中,将子线程(工作线程)中需要更新UI的相关信息传递到主线程,从而实现工作线程对UI的更新。 二、使用方式 Handler的使用方式可以根据发送消息的方式不同而分为两种: Handler.sendMessage()...

haovin的博客 2万+

Handler 使用(详细版)

Handler是Android中用来更新UI 的一套消息处理机制。Handler允许线程间发送Message或Runnable对象进行通信。在Android中UI修改只能通过UI Thread,子线程不能更新UI。如果子线程想更新UI,需要通过Handler发送消息给主线程,进而达到更新UI的目的。Handler负责发送Message到Looper负责从遍历Message,然后直接把遍历的消息回传给Handler自己,通过Handler自身的处理更新UI等操作。主线程、子线程间通信简单流程。

轻描时光 1458

Handler标准用法(推荐)

Handler经常会出现泄露问题,原因是handler持有了activity的引用后导致activity无法被回收,如下是推荐使用的标准用法

知识空间 2620

Handler 消息机制底层解析:从应用层到 Framework SystemServer 全链路源码拆解

本文深入解析Android Handler消息机制的核心原理与应用。通过拆解Handler、Message、MessageQueue、Looper四大组件,对比App主线程和SystemServer系统进程的消息循环差异,重点剖析同步屏障、IdleHandler、消息复用池等底层机制。文章结合Android13源码,详细解释Looper死循环不卡顿的Linux管道阻塞原理,分析Handler内存泄漏的完整引用链并提供两种解决方案,同时给出大厂面试标准答案和工程开发规范。

郑伟强dev的专栏 174

标准恢复二极管整流器的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告

报告页数: 150 图表数: 100 报告价格:¥16800 本文研究全球与中国市场标准恢复二极管整流器的发展现状及未来发展趋势,分别从生产和消费的角度分析标准恢复二极管整流器的主要生产地区、主要消费地区以及主要的生产商。重点分析全球与中国市场的主要厂商产品特点、产品规格、不同规格产品的价格、产量、产值及全球和中国市场主要生产商的市场份额。 主要生产商包括: Yangzhou Yangjie Vishay Intertechnology Power Semiconductors Inc Nexperia B

Fj69258的博客 5849

handler的使用总结

​​主要用途​​ 在​​后台​​执行​​耗时任务​​(如I/O操作、计算),​​不阻塞UI​​ 从​​子线程发送消息​​,以便在​​主线程​​中​​安全更新UI​​。​​适用场景​​ 适合​​长时间运行​​、需​​顺序处理多个任务​​的后台队列 适合​​单次​​或​​不定期间隔​​的​​UI更新​​或​​轻量任务​​。

HZUST的博客 694

FRM模型五:Brinson业绩归因

利用Brinson对基金组合业绩进行归因分析。

stonesssssss的博客 3008

扒光 Handler,赶紧来瞧一瞧

/ 今日科技快讯 /近日,据网信办官网消息,针对当前豆瓣网存在的严重网络乱象,3月15日,国家互联网信息办公室指导北京市互联网信息办公室派出工作督导组,进驻豆瓣网督促整改。/ ...

郭霖 169

Ubuntu的初步环境配置(VMware)

4.屏幕显示不全解决完后,在试用Ubuntu里面,直接双击“安装Ubuntu 20.04.6 LTS”。如果不存在“屏幕显示不全”的问题,直接点击安装即可,大致安装步骤与以下步骤类似。15.点击现在重启,重启成功后,会出现“清除安装介质”的问题。19.此时点开火狐,可以上网,但只可输入英文,不可以输入中文,具体解决方法见3.2。3.进入安装界面,此时可能会出现“屏幕显示不全”的问题,具体解决方法见3.1。8.选择“正常安装”、“安装Ubuntu时下载更新”,点击继续。最后,点击保留更改,设置成功。

森菌蛙诺的博客 2278

DC/DC恒压输出控制原理与应用

DC/DC恒压输出控制

propor的专栏 4282

结合源码拆解Handler机制

当初在讲App启动流程的时候,它的整个流程涉及到的类可以汇总成下面这张图:那时着重讲了AMS、PMS、Binder这些知识点,有一个是没有对它进行详细讲解的,那就是常见的Handler,它不仅在这个流程里作用在ApplicationThread和ActivityThread进行通信,它在整个安卓体系中也扮演着重要的角色,所以也是面试过程中经常被问到的知识点,所以接下来将对它的源码进行分析。

maniuT的博客 456

[明道云] -基础教学5- 明道云 40 种控件详解与场景解析

明道云工作表提供40种业务控件,涵盖文本、数值、关联、公式等类型,支持各类业务场景。文本类支持多行输入、正则校验;数值/金额类提供进度条、百分比显示等功能;关联类实现多表数据引用;公式/函数类支持复杂逻辑运算;自动化类包括打印模板、API调用等控件。合理使用这些控件可提升数据收集质量和自动化效率,同时需注意控件联动的性能影响和权限配置。关键控件包括关联记录、级联选择、公式计算等,适用于订单管理、客户信息关联等业务场景。

每日出拳老爷子的博客 8542

《从源码到实战:Android Handler 机制的完整工作链路拆解》

Handler机制是Android框架的基础,用于解决多线程环境下的UI更新和任务调度问题。它基于“生产者-消费者”模型,主要由Handler、Looper和MessageQueue三个核心类组成。简单来说,Handler负责发送和处理消息,Looper负责循环处理消息队列,MessageQueue则存储待处理的消息。这种机制确保了线程安全,避免了直接操作UI线程带来的风险。Android Handler机制通过清晰的源码设计和稳健的工作链路,为多线程通信提供了可靠解决方案。

stchgjjdkklklss的博客 745

rk3568 rk628桥片hdmi转lvds

RK628 是瑞芯微全新推出的视频桥接芯片,支持丰富的显示接口,支持高分辨率大屏产品转换需求。基于DRM、FB的显示框架易于使用。 输入信号支持:HDMI、RGB、BT.1120,输出信号支持 HDMI、GVI、Dual LVDS、Dual MIPI、MIPI-CSI、RGB、BT.1120,最高支持4K 60fps 输入/输出转换,并且支持输入到输出 1/4~4倍的缩放。

weixin_35723192的博客 1131

基于深度学习的人脸识别考勤管理系统,采用YOLOv11和Dlib算法实现人脸识别和考勤签到,前台人脸识别和签到系统 + 后台人脸和考勤管理系统,全网独发

基于深度学习的口罩人脸识别的考勤管理系统,采用YOLOv11和Dlib算法实现人脸识别和考勤签到,前台人脸识别和签到系统 + 后台人脸和考勤管理系统,全网独发

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 1828

《STL源码剖析》中关于set_new_handler的理解

在阅读侯杰的《STL源码剖析》的时候,在书中的p45遇到一段代码,书中并没有给予set_new_handler详细的解释,查阅资料发现网上的解释并不是那么尽如人意,在查阅了《effective C++》这本书之后,总结写出了这篇博客。

在地图上飞行 2341

GD32F470移植LWIP协议,PHY芯片DP83848I

也就是说前24位是有规定的,其中48位MAC中的前几位也是有着对应的含义的。2、旧版LWIP(如1.4.1)存在DHCP状态机卡死问题,建议升级至2.1.3+。

m0_61973119的博客 1591

结合源码拆解Handler机制(1),HarmonyOS鸿蒙面试宝典下载

可以看到,此时就是先创建一个prev对象,用来记录当前消息的上一个消息对象的,让它等于p(也就是第三条消息对象),然后p等于p(第三条消息对象)的下一个消息对象(此时是为第二条消息),所以现在p就为第二条消息对象,之后就判断当前对象(第四条消息对象)的时间when是否小于第二条消息对象的when,如果成立,则不用再循环,走msg.next = p;但单链表的好处就是,如果要在某个位置上插入或者删除某个节点对象,直接操作就可以(把它的指向下一个对象的引用的指向进行更改就可以)。

2401_84167046的博客 657

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

结合源码拆解Handler机制(2),2024年最新字节跳动面试经验

可以看到,此时就是先创建一个prev对象,用来记录当前消息的上一个消息对象的,让它等于p(也就是第三条消息对象),然后p等于p(第三条消息对象)的下一个消息对象(此时是为第二条消息),所以现在p就为第二条消息对象,之后就判断当前对象(第四条消息对象)的时间when是否小于第二条消息对象的when,如果成立,则不用再循环,走msg.next = p;所以,handler的消息排序机制也就是靠这个时间when来决定谁先谁后,小的那个排在大的后面,借由单链表的插入特性来进行插入。

2401_84167046的博客 803

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

2024年鸿蒙最新结合源码拆解Handler机制(3),程序员的面试题

在分析这个方法前,先来想一想队列这个概念,可能有部分人对它有点陌生,这里解释一下,MessageQueue是一个队列,它并不是数组或者集合那样,是定义一个有容量的“容器”,而是通过单链表Message这个结构://单链表Message作为MessageQueue持有的变量,Message里有一个指向下一个Message对象的引用,因此Message消息其实是一个单链表形式串联在一起的。

2401_84853048的博客 495

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

你真的会用Handler?

前言 Handler消息机制是Android中提供的一种线程间通信机制,说到线程间通信,懂Java的我们都知道可以通过等待唤醒机制(wait/notify)实现线程间通信,但是这种机制会产生锁的竞争、线程的阻塞。响应不是很快,所以google的大佬们自己开发出一套线程间通信机制-Handler消息机制。 Handler消息机制符合生产者消费者模型,有以下几个角色组成。Looper、MessageQueue、Message、Handler Handler整体工作流程 简要概述下Handler消息机制的整体运作

李林杰的博客 396

Netty源码分析第4章(pipeline)---->第2节: handler的添加

Netty源码分析第4章(pipeline)---->第2节: handler的添加 Netty源码分析第四章: pipeline 第二节: Handler的添加 添加handler, 我们以用户代码为例进行剖析: .childHandler(new ChannelInitializer<Socke...

weixin_30555125的博客 219

网易有道安卓二面翻车复盘:无实习非科班如何死磕Handler与Binder源码

在Android开发岗的面试中,Handler消息机制与Binder跨进程通信是绕不开的高频考点。Handler通过Looper死循环与nativePollOnce阻塞-唤醒机制实现线程切换,而Binder借助mmap内存映射完成一次拷贝,从而提升IPC效率。理解这些底层原理,不仅是应对面试连环追问的关键,更是设计健壮缓存、优化应用性能、搭建图片加载库等工程实践的基础。无论是主线程消息调度、进程间通信还是生命周期管理,都离不开对源码级实现逻辑的把握。本文真实复盘一位无实习、非科班的211学生投递网易有道安卓

weixin_33770878的博客 386

深度剖析 DouYin 源码:Downloader + Handler 管道式架构设计之美

说起抖音爬虫项目,DouYin 源码绝对是一个值得反复研读的范本。这个名为"API of DouYin for Humans"的开源项目,用不到两千行代码,把"抓取热门视频和音乐"这件复杂的事,做成了一套清晰优雅的管道式架构。今天这篇文章,就带你从零读懂 DouYin 源码中的 Downloader + Handler 双角色设计,看看它是如何把采集、下载、存储层层解耦的。 DouYin 的设计

gitblog_00330的博客 402

Android 从Java线程到Handler机制源码分析

从 Java 线程、锁机制引出 Android 线程、HandlerThread,再到 Handler 机制、同步屏障机制分析,一文明白其中的原理。

孙先森的博客 1280
上一篇: 为什么 Android 要使用 Binder 作为 IPC 机制?
下一篇: Handler 相关知识,面试必问
不秃头de程序猿
博客等级 码龄5年 4089粉丝 1478原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值