Android线程通信机制详解:Handler、Looper与MessageQueue实战避坑
搞Android开发的人几乎都绕不开“线程通信”这四个字。只要程序里出现耗时操作比如网络请求、图片加载、数据库读写就必须放到子线程但子线程干完活儿又没法直接碰UI控件这时候就需要一套机制把数据从子线程“传”回主线程。这中间牵扯到的Handler、Looper、MessageQueue既是面试高频考点也是日常开发里最容易埋雷的地方——内存泄漏、消息堆积、ANR哪个都跟它有关。这篇文章不是单纯讲API怎么调用而是把线程通信这套机制的底层逻辑、各种通信方式的选型取舍、以及我自己在实际项目中踩过的坑都梳理一遍。适合刚入门想知道Handler到底是什么的新手也适合用Handler写了好几年代码但一直没搞懂消息屏障、IdleHandler这些细节的老手。读完不敢说你就能写出完美的并发代码但至少在面试被问到“Handler机制怎么设计”时心里是有底的。1. 线程通信到底在解决什么问题1.1 为什么子线程不能直接更新UI这个问题很多教程都一笔带过说“Android规定子线程不能更新UI”但没讲清楚为什么有这个规定。先说结论不是技术上做不到而是设计上不允许。Android的UI控件不是线程安全的如果允许多个线程同时操作一个TextView或者一个Button会出现数据不同步的状态轻则界面闪烁错乱重则直接崩溃。与其给所有UI类加锁导致性能下降不如干脆规定只有主线程能干UI的活儿。这条规定在代码层面是有保障的。你去调用textView.setText()的时候最终会走到ViewRootImpl里的checkThread()方法它会把当前线程和创建视图时的线程做比对不一致就抛CalledFromWrongThreadException。这就是我们常说的“主线程更新UI”的由来。但这条规定并不绝对。我见过有人用requestLayout()在某些场景下绕过检查也见过开发者在子线程里创建了一个独立的Window去画内容。这些都属于非常规操作日常业务代码最好不要碰。老老实实走线程通信才是最稳妥的做法。1.2 线程间通信的几种常见思路抛开Android框架线程通信在计算机世界里其实有一堆现成方案共享内存、管道、Socket、消息队列、信号量。Android选的是“消息队列Handler”这条路线原因也很直观UI场景里子线程往主线程发数据是典型的“生产者-消费者”模型需要的是一个异步的、不阻塞调用方的通道而不是一个同步的返回值。你可能会问直接用一个BlockingQueue不也能实现吗确实能但Android的消息机制在队列基础上加了几个关键能力Message可以复用来减少对象创建、Looper负责循环读取队列、Handler可以指定处理线程、还支持延迟消息和空闲任务。这些能力对于UI线程这种既要高响应又要低卡顿的场景都是刚需。还有一个容易忽略的点消息机制不只是“子线程传主线程”这一条单向通道。你可以手动创建带Looper的子线程让主线程往子线程派活比如写日志、批量处理数据库操作。这种场景同样基于Handler机制只是方向反过来了。理解了这一层你对线程通信的理解就立体了。2. 核心消息机制拆解Handler、Looper、MessageQueue怎么配合2.1 三个组件各司其职到底谁管谁很多初学者看到Handler、Looper、MessageQueue三个名词就头大其实用生活化的方式理解就简单了Looper是流水线上的工人MessageQueue是工人旁边排队的待办箱Handler是往待办箱里放纸条的人同时也是告诉工人“纸条上的活儿干完该通知谁”的人。每个线程只要调用了Looper.prepare()就会在本地变量里保存一个唯一的Looper对象同时Looper在构造时会创建一个MessageQueue。主线程在ActivityThread.main()里已经替你调好了prepare和loop所以你直接new Handler()就能往主线程发消息。子线程默认没有Looper必须手动准备。关键点在于Handler在创建时就会绑定当前线程的Looper。你用哪个线程new Handler()你的handleMessage就运行在哪个线程上。这一点经常被忽略很多人以为handler一定运行在主线程其实不是它在哪个线程创建就绑定哪个线程的Looper。所以你可以放心地在子线程建一个Handler去接收主线程派下来的任务。2.2 一条消息从发出到处理完整走一遍拿最常见的场景举例子线程执行完耗时任务想通知主线程刷新UI。第一步子线程调用handler.sendMessage(msg)或者handler.post(runnable)。如果是post内部也会把Runnable包装成一个Message。紧接着sendMessageDelayed最终调用了enqueueMessage()把消息按时间顺序插入到MessageQueue里。注意是“按时间顺序”不是无脑往队尾插因为Handler支持延时消息所以要保证when字段递增。第二步主线程的Looper.loop()进入一个死循环不停地从MessageQueue.next()里取出消息。如果当前没有到时间的消息主线程会阻塞在native层的nativePollOnce此时主线程不耗CPU也就是Android“没有消息时主线程不卡顿”的底层原因。这个阻塞机制依赖Linux的epoll事件到了之后会被唤醒。第三步loop()取到消息后调用msg.target.dispatchMessage(msg)。这个target就是当初发消息的Handler。dispatchMessage里会判断Message有没有设置Callback有就直接执行没有就回调你重写的handleMessage。到这里一条消息就完整地从子线程传递到主线程执行了。这里面有个教科书里经常不强调的细节Message是有对象池的。你用Message.obtain()而不是new Message()用完之后Recycler这个链表会把Message回收。为什么要这么做因为主线程每秒要处理大量消息如果每个都new一个对象GC压力会非常大UI就会因为频繁GC出现卡顿。所以正规写法一定是obtain 手动置空字段。2.3 容易被忽略的同步屏障与IdleHandler这两个东西面试问得不勤但源码里无处不在理解了它们才算真正抠透Handler机制。同步屏障叫postSyncBarrier它的作用是让队列里所有“同步消息”全部暂停只放行“异步消息”。平时我们发的消息默认都是同步消息只有被标记为异步的Message才不受屏障拦截。这套机制在Android渲染流程里用得非常狠比如Choreographer要保证帧消息优先执行就会先插入一个同步屏障把一般业务消息挡住等帧绘制完成再移除屏障。这也是为什么UI卡顿严重时你handler里的延迟回调也会跟着往后拖延。IdleHandler就更好理解了当消息队列空闲了也就是当前没有需要立刻处理的消息系统会调用你注册的IdleHandler。适合做那些“不急但迟早要做”的事比如界面加载完成之后预加载下一页数据、延迟初始化一些非关键组件。我自己用它在首页做过一版图片预加载对启动耗时几乎零影响。但要注意IdleHandler里不能做耗时操作因为它会阻塞主线程的下一条消息派发后端一忙UI就掉帧。3. 线程通信的常用姿势与选型思路3.1 runOnUiThread、View.post 与 Handler.post 该用哪个除了直接写Handler线程通信在Activity和View的包装下还有几个简便方法。runOnUiThread是Activity提供的方法内部其实就是判断当前线程如果是主线程就直接执行否则走mHandler.post(action)。它的优势是简洁适合在Activity内部做完异步任务后快速刷新UI。缺点是耦合了Activity的Handler如果你在非Activity的普通类里想用就没那么顺手了。View.post也很常用内部会拿到View所属的Looper也就是主线程Looper然后调用getRunQueue().post(runnable)执行。有个特殊场景特别适合用View.post当你在onCreate里想拿一个View的宽高但此时View还没完成测量直接getWidth拿不到数值。用View.post把任务丢到消息队列等布局完成之后再执行就能拿到正确的宽高。这个技巧做过度动画、初始化列表时非常实用。Handler.post则最底层自由度最高。你可以用它做定时任务、延时任务、也可以配合HandlerThread创建完全独立的消息循环。我做项目时的原则是能用一个现成的高级封装就不用裸Handler但一旦涉及线程池调度、自定义消息优先级、批量任务分发就直接回到Handler本身。它是地基另外两者是在地基上盖的房子。3.2 HandlerThread自带Looper的后台线程如果只是偶尔让子线程干一件事开一个普通线程就行。但如果你的App里到处都要往同一个后台线程丢任务比如写日志、刷数据库、上报埋点每次都new一个Thread就会造成很无谓的开销而且并发操作数据库还有锁竞争的问题。这时候用HandlerThread是最好的选择。HandlerThread本质就是一个普通Thread但它内部在run()里执行了Looper.prepare()和Looper.loop()等于自带了一个消息循环。创建方式也很简单HandlerThread workerThread new HandlerThread(worker); workerThread.start(); Handler workerHandler new Handler(workerThread.getLooper()); workerHandler.post(new Runnable() { Override public void run() { // 这里运行在worker线程里按队列顺序执行 } });这样所有post到workerHandler的任务都会在workerThread上排队执行天然串行。做数据库批量写入、日志打印这种顺序敏感任务很合适。需要注意的是HandlerThread用完记得调用quitSafely()它会把当前排队中的任务处理完再退出而不是暴力打断。如果直接调用quitSafely()之后还想复用这个线程抱歉不行Looper的loop一旦退出就无法重新开启。这也是我踩过坑的地方所以现在写代码都是把HandlerThread的生命周期管理好或者在组件内部常驻。3.3 AsyncTask为什么建议放弃协程凭什么能上位聊到线程通信总有开发者问现在还用不用AsyncTask。我的态度很明确业务代码里不要用了面试的时候能说出它的问题反而是加分项。AsyncTask的问题在于它绑定Activity或者Fragment的生命周期一旦页面销毁但任务还在跑回调拿到弱引用后操作UI要么空指针要么内存泄漏。再加上Android 11已经把AsyncTask标记为deprecated说明官方也对它的设计不抱希望了。Kotlin协程能上位不是因为它能“替代”Handler——底层线程调度依然依托于这套消息机制而是因为它在编码层面把线程切换这件事讲成了人话。你不需要写回调嵌套也不用手动post一个withContext(Dispatchers.Main)就能指定代码运行在哪个线程。尤其配合Retrofit、Room这些框架协程凭证让异步代码看起来像同步代码一样顺畅。但话又说回来协程只是一个更高级的框架它解决不了消息机制本身的问题。你如果理解Handler的原理再看协程的suspend和continuation就会有“原来如此”的通透感。底层知识点永远不会过时过时的只是某一层封装方式。4. 实战封装一个稳定可控的线程通信组件4.1 一个HandlerThread生产消费模型的设计过程说再多理论不如直接看一个能跑的封装。我在之前某个项目里需要统一管理一批后台任务要求任务按顺序执行、能主动取消、能和主线程通信。当时没有用第三方的任务库因为需求足够简单引入框架反而臃肿。就用HandlerThread Handler自己做了一个轻量组件。核心思路建立一个串行的后台队列外部往队列里提任务任务执行结果通过回调切回主线程。考虑到多个地方会发起任务我设计了一个单例外壳内部持有HandlerThread、后台Handler和主线程Handler。public class TaskDispatcher { private static volatile TaskDispatcher sInstance; private final HandlerThread mWorkerThread; private final Handler mWorkerHandler; private final Handler mMainHandler; private TaskDispatcher() { mWorkerThread new HandlerThread(task-dispatcher); mWorkerThread.start(); mWorkerHandler new Handler(mWorkerThread.getLooper()); mMainHandler new Handler(Looper.getMainLooper()); } public static TaskDispatcher getInstance() { if (sInstance null) { synchronized (TaskDispatcher.class) { if (sInstance null) { sInstance new TaskDispatcher(); } } } return sInstance; } public void postTask(Task task) { mWorkerHandler.post(() - { // 在后台线程执行耗时业务 Object result task.run(); // 切回主线程把结果交给调用方 mMainHandler.post(() - task.onResult(result)); }); } public interface Task { Object run(); void onResult(Object result); } }这种封装还有优化的空间比如结果带泛型、支持取消任务、延迟执行、任务超时监控等。但核心骨架就是这两行handler一个负责“干活线程的队列”一个负责“结果回传的桥梁”。理解了这个骨架你在任何项目里都能按需扩展。4.2 为什么选择双Handler而不是单Handler有人会问为什么不直接用一个主线程Handler把耗时任务放在一个普通线程里执行、完成后post回主线程当然可以但这样耗时任务的调度分散在各处维护成本高。双Handler结构的核心价值在于所有后台任务的调度入口都收敛到一个地方队列模型清晰调试也方便。单例为什么要用volatile synchronized双重检查锁因为多线程同时调用getInstance()时可能出现null判断的不一致而volatile保证实例可见性、synchronized保证只有一个线程创建实例。虽然这段模板代码看起来有些过时但它仍然是Java里最经典、最不会出错的单例写法。我实际使用时还会在Task里加一个cancel()标记因为handler.removeCallbacksAndMessages(null)可以清理队列但已经执行到一半的任务无法暴力打断。所以更合理的做法是每个任务执行前先检查是否已被取消如果取消了就直接跳过不再把结果回传主线程。这个细节很琐碎但能帮你避免大量“页面已销毁但回调还在执行”的崩溃。4.3 Handler订阅者模式让多个页面同时收到线程消息如果你做过IM类的消息推送会发现一个场景同一个消息到来时聊天页、会话列表、未读角标都要同步更新。如果每个模块都通过自己的Handler去发消息就得手动写N个handler引用维护起来很头疼。这时候就要在Handler的基础上做一层订阅分发。思路不难中心消息类持有一个Mapkey是消息类型value是Handler列表。外部模块注册自己关心的消息类型当后台线程拿到新数据时通过对主题发布消息中心类遍历对应Handler列表分别post。这就是典型的观察者模式只是底层投递仍然用的Handler。这种方案的好处是发消息的人不关心谁在听收到消息的人也不关心消息从哪来。缺点是注册的生命周期要管理好页面销毁时一定要取消注册否则会把Activity整个泄漏在Handler列表里。这也是我反复强调的只要用到Handler就一定要问自己一句话“这个Handler会不会持有一个本该被回收的对象”5. 高频问题排查与实战避坑5.1 内存泄漏非静态内部类和匿名Handler都是坑Handler引发内存泄漏是线程通信里最经典的坑。场景还原一下你在Activity里写了一个内部的Handler实现类比如private Handler mHandler new Handler() { Override public void handleMessage(NonNull Message msg) { // 处理逻辑 } };这行代码看起来没什么问题但它有一个隐藏的引用链Message-Handler-Activity。如果你发了一条延时消息比如延迟10秒那么在这10秒内Activity因为用户的返回操作已经销毁但消息还在队列里队列又被主线程的Looper持有Looper又是个全局存在。结果就是整个Activity引用着一层一层被留住垃圾回收根本动不了它。这就是内存泄漏。解决办法也不复杂。第一个思路是把Handler改成静态内部类并且持有Activity的弱引用private static class SafeHandler extends Handler { private final WeakReferenceMainActivity mActivityRef; SafeHandler(MainActivity activity) { mActivityRef new WeakReference(activity); } Override public void handleMessage(NonNull Message msg) { MainActivity activity mActivityRef.get(); if (activity null || activity.isFinishing()) { return; } // 处理逻辑 } }第二个思路是在onDestroy里主动清掉消息Override protected void onDestroy() { super.onDestroy(); mHandler.removeCallbacksAndMessages(null); }两种方式我都用过实际经验是静态内部类WeakReference是根治removeCallbacks是补救。线上环境我两个都做因为总有些消息在Activity销毁后才被post进来单靠removeCallbacks并不完全覆盖。5.2 消息堆积导致卡顿如何定位和治理另一个高频问题是消息堆积。症状表现为界面卡顿、Handler回调不执行、点击响应慢。原因往往是有人往主线程post了大量消息或者某个handler消息执行太慢把队列堵住了。排查思路分三步。第一步看主线程的调用栈通过systrace抓取一段时间内主线程到底在忙什么。第二步看消息队列里囤了多少消息可以临时在MessageQueue的next()方法里打点打印每条消息的when和target从而定位是哪个Handler的消息量异常大。第三步看有没有高频轮询我遇到过某个版本在动画回调里反复post消息一帧都没停结果就是消息量爆炸式增长。治理手段也很直接合并不必要的消息、把非UI必须的任务挪到子线程队列、减少延时消息的滥用。比如列表滚动时不要再往主线程post图片下载任务而应该交给线程池去拉拉完再通过Handler回传一个结果。消息队列是主线程的命脉它的压力直接影响用户体验。5.3 HandlerThread无法复用以及quit带来的连锁问题还有一个容易被新手踩的坑HandlerThread调用quit()之后getLooper()再取就是null。因为你线程的run()已经执行完毕Looper被清空了直接导致new Handler时抛出异常。这个问题一旦发生在线上经常是偶发性崩溃排查起来特别费劲。所以我的习惯是任何HandlerThread都封装在一个持有类里由持有类统一管理它的生命周期。不要在外部随意调用quitSafely()更不要在退出之后还往线程里post任务。如果确实需要不断创建和销毁后台线程建议用线程池而不是每次手动new一个HandlerThread。再补充一个小细节Looper.loop()本身是个死循环方法它内部不断调queue.next()取消息。如果MessageQueue里根本没有消息了主线程会一直阻塞在native层。这个状态不是性能问题反而恰恰是Android让主线程“空闲”的省电机制。你要判断主线程是否正常不是看它有没有在跑而是看它阻塞时有没有出活。5.4 线程通信常见问题速查表有些问题我反复在团队答疑里被问到整理成一张表方便对照排查。问题现象根本原因推荐解决方案子线程更新UI崩溃违反UI线程单线程模型使用Handler.post或runOnUiThread切回主线程Activity销毁后回调还在执行Handler持有Activity引用静态内部类WeakReference或removeCallbacksAndMessages延时消息时间不准消息队列被同步屏障屏蔽检查是否有渲染相关屏障占用或使用异步Handler队列消息堆积、卡顿主线程post了过多消息将非UI任务迁移到子线程或HandlerThreadHandlerThread复用报错quit后Looper已销毁不要复用设计好创建与销毁的生命周期多个模块收消息靠手动转发缺乏统一的消息分发机制用Handler做基础的订阅分发模型消息对象频繁创建导致GC直接new Message过多使用Message.obtain()复用对象每次遇到诡异的问题我都会回到消息机制的本质上去想这条消息是谁发出的它要被谁消费它所在的队列是否健康它的deleyed时间是否合理。这四个问题一想清楚90%的线程通信问题都能定位出来。我个人在实际项目里还有一个习惯凡是涉及Handler的代码统一在提交前过一遍内存引用关系。画一条从Message到持有者的引用链看看有没有不该活得这么久的东西。这个方法看着笨但真的帮我提前拦下来过好几个线上崩溃。线程通信这件事千万不能只停留在“会用API”的层面把引用关系、执行顺序、生命周期想透才算真正入了门。

相关新闻

PL/0编译原理课程设计:从词法分析到代码生成的修改扩充全攻略

PL/0编译原理课程设计:从词法分析到代码生成的修改扩充全攻略

简介:编译原理课程设计中针对PL/0编译器进行修改与扩充的完整工程包,覆盖赋值运算符、-,以及Pascal风格FOR、DOWNTO循环语句等核心语法改造,适合计算机专业学生做编译原理实验或课设时参考。压缩包共42个文件,包含PL0源…

2026/10/12 7:48:31 阅读更多 →
将Node.js升级到最新版本:用TaoToken统一Key跑通升级后AI工具链

将Node.js升级到最新版本:用TaoToken统一Key跑通升级后AI工具链

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 7:48:31 阅读更多 →
Zynq裸机UDP通信实战:lwIP发送Hello World与系统不响应问题排查

Zynq裸机UDP通信实战:lwIP发送Hello World与系统不响应问题排查

1. 项目背景与核心需求拆解1.1 这个项目到底在做什么先把场景说清楚。这个项目的核心目标是在Zynq平台上实现一个最基础的网络通信功能:开发板通过UDP协议,向上位机发送一条"Hello World"字符串。听起来简单得不能再简单,但做过Zyn…

2026/10/12 7:47:30 阅读更多 →

最新新闻

数据复制深度拆解:从HDFS块复制到CDC同步的机制、实践与容灾设计

数据复制深度拆解:从HDFS块复制到CDC同步的机制、实践与容灾设计

大数据领域做久了,你会发现一个很朴素但又绕不开的现实: 数据复制 几乎贯穿了所有核心系统的生命周期。无论是离线数仓里的表同步、实时链路里的CDC采集,还是跨机房容灾里的镜像复制,本质上都在做同一件事——把一份数据从A点搬…

2026/10/12 9:23:59 阅读更多 →
开源大模型权重质变:推理优化、量化与微调工程实践指南

开源大模型权重质变:推理优化、量化与微调工程实践指南

1. 从"权重开放"到"能力平权":一场静默的行业拐点 过去两年,我一直在跟踪各类开源模型权重发布后的实际落地情况。说实话,早期大部分所谓"开放权重"的模型,更多是实验室里的展示品——参数量大、推…

2026/10/12 9:23:59 阅读更多 →
配电网多目标Pareto重构:Matlab实现NSGA-II的实战经验与代码解析

配电网多目标Pareto重构:Matlab实现NSGA-II的实战经验与代码解析

配电网多目标Pareto重构,核心就一句话:通过改变分段开关和联络开关的开合状态,重新编排配电网的供电路径,让网损、电压质量、开关操作成本等多个目标同时尽可能好。这个问题我前后做了一段时间,用Matlab实现了多套智能…

2026/10/12 9:23:59 阅读更多 →
把手机变成AI服务器:openclaw-termux SSH远程访问配置实战教程

把手机变成AI服务器:openclaw-termux SSH远程访问配置实战教程

AI 应用LLM 网关大模型移动开发 【免费下载链接】openclaw-termux Run OpenClaw AI Gateway on Android — standalone Flutter app with built-in terminal, web dashboard, and one-tap setup. Also available as a Termux CLI package. 项目地址: https://gitcod…

2026/10/12 9:23:58 阅读更多 →
自己动手实现TreeMultiSet:基于TreeMap的有序可重复集合

自己动手实现TreeMultiSet:基于TreeMap的有序可重复集合

1. 从一个真实的数据统计需求说起去年帮一个做电商的朋友处理订单数据时&#xff0c;遇到一个挺典型的问题&#xff1a;他们需要统计每个商品在一天内的被下单次数&#xff0c;并且要按商品ID排序输出。第一反应是用TreeMap<Long, Integer>&#xff0c;key 是商品ID&…

2026/10/12 9:22:58 阅读更多 →
PS5折腾指南:系统配置、存储扩展、远程游玩与散热维护

PS5折腾指南:系统配置、存储扩展、远程游玩与散热维护

PS5到手三个月后&#xff0c;我发现自己陷入了一个尴尬循环&#xff1a;开机看一眼、随便通关一个进度、然后切出去看手机&#xff0c;主机外壳摸起来都能煎鸡蛋。直到我给自己定了个"AnyPS5"计划——不把这台机器当普通游戏机&#xff0c;而是当成一台可折腾的娱乐终…

2026/10/12 9:22:58 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天&#xff0c;画面可以做到绝对的锐利、平滑与无瑕。然而&#xff0c;当一张秋日手账插画或拍立得照片过于“平整无瑕”时&#xff0c;往往会散发出一种冰冷生硬的“数码塑料感&#xff08;Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中&#xff0c;横排&#xff08;Horizontal Layout&#xff09;早已经成为了绝对的主流。然而&#xff0c;当我们翻开泛黄的线装古籍、宋版木刻诗集&#xff0c;或是欣赏一张茶道雅集的手写便签时&#xff0c;那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点&#xff0c;很多人心里都会悄悄亮起一盏警示灯。 在心理学上&#xff0c;这种现象有一个专门的称谓——“周日夜晚焦虑症&#xff08;Sunday Scaries&#xff09;”。明天又是周一&#xff0c;闹钟又要重新在七点响彻卧房&#xff1b;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介&#xff1a;基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码&#xff0c;面向计算机相关专业课程设计与期末大作业学生&#xff0c;以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程&#xff0c;…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程&#xff1a;键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化&#xff0c;十个新手有八个栽在"往输入框里填东西"这件事上&#xff1a;要么填不进去&#xff0c;要么填了一半&#xff0c;要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程&#xff1a;阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀&#xff1a;什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面&#xff0c;跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →