当前位置: 首页 > news >正文

欢聚时代Android校招笔试拆解:从Handler到性能优化与算法实战

2018年秋天,欢聚时代在成都场发的这套Android A卷,我到现在还留着电子档。当时很多同学拿到卷子第一反应是“基础题真多”,但真正动笔才发现,那些看似基础的知识点,全被换了个角度在考。后来我自己也参与过一些校招出题,才明白这套卷子的设计思路——它不考你会背多少API,而是考你能不能把一个知识点讲透,能不能在代码里避开常见的坑。回头来看,这套题对今天准备Android校招的同学依然有参考价值。

这套A卷的整体风格是“常规但不平庸”:四大组件、Handler、性能优化、网络与JSON解析、算法与逻辑题,基本覆盖了当年Android校招的必考范围。但妙就妙在它把每个方向都往深挖了一层,比如字符串压缩、数组快排、卷子里这些算法题都不算难,却刚好卡在“你能写出来,但不一定能写对”的程度上。今天我就把这份卷子拆开揉碎,结合我后来实际开发中踩过的坑,聊聊每道题背后的考察意图和正确打开方式。

1. 校招笔试的考察逻辑:为什么欢聚时代要这样出题

1.1 Android岗位的筛选漏斗:笔试这关到底在筛什么

先说一个很多同学容易误解的地方:笔试不是用来选“最会写代码的人”,而是用来筛掉“基础概念含糊、代码习惯差、遇到异常就懵”的人。欢聚时代的业务以直播、音视频为主,这类产品对应用的稳定性和性能要求很高,crash率、卡顿、内存占用都是要实时盯的数据。所以他们的笔试内容会明显偏向性能优化和稳定性设计,这是由业务形态决定的。

那套A卷的题目分布我复盘过,大概是这样的结构:

考察模块常见题型考察目的
Java基础集合类、异常、泛型、并发语言底子是否扎实
Android组件生命周期、启动模式、Intent是否真的用过四大组件
消息机制Handler/Looper源码级分析对核心机制的理解深度
性能优化内存泄漏、ANR、布局优化是否有线上问题处理意识
网络与数据JSON解析、HTTP协议是否做过真实网络请求
算法与逻辑字符串处理、排序、链表编码基本功与边界思维

这个结构放在今天的校招里依然是主流,但2018年的卷子有个特点:它不会明确告诉你“这题考内存泄漏”,而是给一段看起来没啥问题的代码,让你找出内存泄漏的地方。这比直接问“什么是内存泄漏”要难得多,因为你需要自己发现问题的能力。

1.2 从真题反推动态:直播类App对Android开发者的特殊要求

如果是普通工具类App的笔试,可能更偏重界面开发和数据展示。但欢聚时代是直播平台,所以他们格外看重几个方向:

第一是消息机制的深入理解。直播间的弹幕、点赞、礼物动画都是高频消息,怎么确保UI流畅不卡顿,怎么把子线程的数据安全地切回主线程更新UI,这直接依赖Handler和Looper的掌握程度。第二是内存管理的敏感度。长时间运行的直播页面容易积累内存泄漏,比如主播间的定时器、网络回调持有Activity引用,这些都是线上性能问题的常见来源。第三是网络与数据解析的工程化能力。直播协议里有大量JSON数据,还涉及弱网处理,笔试里考察JSON的解析性能和容错处理,贴合业务。

所以如果你要投这类公司的Android岗,复习的重点就不能只停留在“会写界面”,而要往“做一个稳定运行的App需要什么”这个方向去思考。

2. 高频考点拆解一:Android核心机制与组件原理

2.1 Activity启动模式:不只是背四种模式的名字

A卷里有一道题几乎是所有Android校招必考的:Activity的四种启动模式是什么?各自的应用场景?以及onNewIntent的调用时机。很多同学能背出standard、singleTop、singleTask、singleInstance,但一深入问就露馅。

我举一个实际场景:直播App里用户点进主播间,再点进另一个主播间,连续跳转。如果全部用standard模式,每进一个直播间就创建一个新的Activity实例,用户的返回栈会越堆越深,内存压力大,返回行为也反直觉。这种情况下,直播间的Activity应该设置成singleTask,保证同一个直播间的Activity只有一个实例。当你从这个直播间跳去开播页面再返回时,如果设置正确,系统会直接复用已有的Activity实例,并且通过onNewIntent把新的Intent传进来,你在里面处理新的主播ID就行。

这里有一个很多人忽略的细节:singleTask和singleInstance启动新实例时,如果目标Activity已经在栈顶,onNewIntent正常回调;但如果它不在栈顶而在栈中,系统会把它上面的Activity全部出栈,再回调onNewIntent。你要是没处理onNewIntent里更新数据,就会发生“点进去还是上一个主播的画面”这种线上bug。

实操心得:我在开发中处理直播间跳转时,都是配合Intent.FLAG_ACTIVITY_CLEAR_TOP来用,这样既能复用实例,又能把层叠的中间页面清理干净,避免返回栈越积越长。笔试里如果让你写代码,这个flag的组合使用会是加分点。

2.2 Service与IntentService:区别背后的设计思想

卷子里有一道题是问Service的两种启动方式和区别,以及IntentService的特点。这个题目现在看依然经典,因为它考察的是“有没有在真实项目里用过Service”。

startService和bindService的区别,背诵版答案是:startService启动后与调用者无关,即使调用者销毁,Service依然在后台运行;bindService则与调用者绑定,调用者销毁时Service解绑并销毁。但笔试更想看到的是你对实际开发的理解,比如长时间后台播放音乐用startService,跨页面获取Service通信用bindService。

IntentService这个考察点有个考点容易忽略:它内部通过HandlerThread把onHandleIntent里面的操作放在子线程执行,执行完自动调用stopSelf。当年很多同学不理解为什么需要它,其实就是Android早期没有协程、没有RxJava时,想要“在子线程做耗时任务,做完自动停”的最简单方案。现在已经不推荐用IntentService了,因为生命周期不可控,但笔试如果出了源码解读,你要说得清它内部的HandlerThread和stopSelf逻辑。

2.3 ContentProvider与URI结构:敏感点藏在路径匹配里

热词里我看到了一些奇怪的URI,比如content://com.ss.android.uri.key/external_root/android/data/com.ss.andro这类路径,还有file:///storage/emulated/0/...这种。虽然看起来像是不完整的用户搜索内容,但它们恰好涉及ContentProvider和FileProvider这两个容易在笔试里出现的知识点。

ContentProvider的URI结构是三段式:scheme + authority + path。scheme固定为content,authority是唯一标识符(通常是包名),path是具体的数据路径。笔试常见的坑是让你写一个匹配特定路径的UriMatcher,很多同学会把路径写错,或者忘记addURI时需要把authority写完整。

FileProvider是ContentProvider的子类,用于跨进程安全共享文件。Android 7.0之后,file://URI不再被允许直接通过Intent暴露给其他应用,必须用content://URI加上临时读写权限。热词里那些奇怪的路径其实是Android应用沙箱目录的访问路径,绕不开FileProvider。笔试如果出一个“如何让两个应用安全地共享一张图片”的题,你就需要答出FileProvider的配置、xml_paths文件的编写、以及grantUriPermission的用法。

实操心得:配置FileProvider时有个坑,paths里cache-path、file-path、external-path的指向要搞清楚,很多人把外部存储根目录直接暴露出去,这在应用审核时是会被拒的。正确做法是只暴露目标子目录,比如共享图片放在files/images下面,paths里就写这个子目录。

2.4 BroadcastReceiver:动态注册和静态注册的适用场景

广播也是高频题,特别是静态注册与动态注册的区别。静态注册在AndroidManifest里声明,App没启动也能收到广播,适合开机启动、网络状态变化这类;动态注册在代码里注册,必须要在注册对象存活期间才能收到广播,适合只在某个页面需要监听消息的场景。

但笔试喜欢挖一个更深的问题:Android 8.0之后,静态注册限制了很多隐式广播。如果问你“为什么Google要做这个限制”,合理的回答是:隐式广播会频繁唤醒大量App,电量和性能消耗很大,限制隐式广播是系统稳定性的需要。如果你能从这个角度回答问题,比单纯背知识点得分高得多。

3. 核心机制深入:Handler、Looper、内存管理这些“送命题”

3.1 Handler消息机制:从一次面试翻车说起

我当年在校招面试时被问过一个场景题:主线程里new一个Handler,子线程里post一个Runnable,这个Runnable是在哪个线程执行?答案当然是主线程,因为Handler默认关联的是创建它时所在线程的Looper。但如果我在子线程里new Handler呢?会直接崩——因为子线程默认没有Looper,你需要在子线程里先Looper.prepare()再Looper.loop()。

这个机制笔试很少让你手写源码,但它会把场景变一变来考你。比如A卷里有一个类似题:以下代码在主线程创建一个Handler,然后在子线程发送消息,问消息在哪个线程处理。很多同学选成子线程,就是因为没理解Handler、Looper、MessageQueue三者之间的关系。

简单梳理一下:一个线程想要有消息队列,需要先调用Looper.prepare(),这个函数内部会创建Looper对象并把MessageQueue一起创建出来;接着调用Looper.loop(),进入一个死循环,不断从MessageQueue里取消息,取到就交给Handler的handleMessage处理。主线程在ActivityThread的main方法里已经帮你调用了prepare和loop,所以你在主线程创建Handler不需要额外处理。

这个机制有个常见的坑:如果主线程的Looper.loop()死循环被阻塞,整个App就会卡死,这就是ANR的根源之一。但真正阻塞主线程的不是loop本身,而是消息队列里有一个耗时任务在排队执行。

实操心得:源码要看得懂但不要死背。面试官更希望听到你用“一个线程配一个Looper、一个MessageQueue,Handler负责把消息扔进队列并处理结果”这样通俗的话把机制讲清楚。

3.2 主线程不能更新UI:这条铁律的本质是什么

这个几乎是Android面试必问的“为什么”。很多人背了答案:因为UI线程不安全。但要深入你还要知道,ViewRootImpl在checkThread()方法里检查了当前线程是不是创建它时的线程,如果不是就抛异常。也就是说,能在子线程里碰UI树的只有创建ViewRootImpl的那个线程,而这个线程通常是主线程。

笔试如果给你一段代码,比如子线程里findViewById然后setText,让你判断会不会崩。答案是:不会立即崩,而是会等到下一次遍历UI树的时候才抛异常。因为ViewRootImpl是在onResume之后才创建并开始检查线程的,如果你在onCreate里开子线程改UI,可能恰好发生在checkThread之前,就不报错。这也是为什么线上偶尔会看到“子线程改UI但没崩”的诡异现象,它不是不崩,只是时机还没到。

理解了这一点,你就能解释为什么Handler是Android里子线程更新UI的标准解法:它不是特别设计的线程安全机制,而是把更新操作通过消息队列切回主线程执行。

3.3 内存泄漏的排查套路:从一道改错题学方法

A卷里有一段模拟代码,我印象很深:一个Activity里持有一个静态的TextView引用,然后问会不会内存泄漏。很多同学答“静态变量持有Activity的View,但因为View本身也持有Activity的引用,所以会泄漏”。

实际答案是显而易见的,但背后的排查方法才是考点。内存泄漏的本质是生命周期长的对象持有了生命周期短的对象引用。静态变量、单例、Handler、内部类、匿名内部类、AsyncTask,这些都很容易在无意中持有Activity。

几种常见泄漏场景,笔试很喜欢混着出:

场景泄漏原因解决方式
静态View引用静态变量持有View,View持有Activity使用弱引用或及时置空
Handler发送延迟消息延迟消息持有Handler,Handler持有Activity在onDestroy移除消息并断引用
内部类隐式引用非静态内部类持有外部类改为静态内部类+弱引用
单例持有Context单例长生命周期持Activity Context使用ApplicationContext
资源未关闭Cursor、Stream未关try-with-resources或finally关闭

实操心得:实际开发中我用LeakCanary来检测泄漏,但笔试不会让你写工具,而是让你识别场景。你只要记住一个原则:任何短生命周期对象被长生命周期对象持有引用,就是泄漏。

3.4 ANR的定位与避免:笔试里怎么“设计”一个稳定应用

ANR全称Application Not Responding,笔试会问触发条件是什么。答案是输入事件5秒内没响应、BroadcastReceiver的onReceive 10秒内没执行完、前台Service 20秒内没执行完。但有人会忽略一个更细的知识点:输入事件超时是5秒,但如果有连续的输入事件在排队,超时时间是从第一个事件开始算起的。这个细节在选择题里很容易把人绕进去。

避免ANR的方法也常常作为问答题出现。核心思路就是两条:主线程只做UI操作,耗时操作全部放到子线程;子线程做完需要通过Handler或者runOnUiThread切回主线程更新UI。笔试里如果能额外提到使用ViewStub延迟加载、使用异步加载框架、避免在onCreate里做太多初始化,都能体现你的经验。

4. 工程实操:网络请求、性能优化与代码习惯

4.1 网络框架的选型思路:从笔试题目看架构设计

2018年的卷子在网络方面会问OkHttp的拦截器机制,以及Retrofit的原理。用过的同学能答上来,但深度不够。比如问你Retrofit是怎么样把接口方法变成请求的,你要能说到动态代理:Retrofit用Java动态代理生成接口的代理对象,每个方法在被调用时解析注解,构建出一个ServiceMethod,再交给OkHttp执行。

热词里也有android studio下载、android sdk官网下载这样的搜索词,说明很多准备面试的同学会用Android Studio做各种实验。其实笔试里不会考IDE的下载,但会考你有没有做过真实项目,因为真实的网络请求必定会涉及这些东西:

  • 如何配置权限:INTERNET权限是必须的,而且Android 9.0之后默认禁止明文HTTP流量,需要在manifest里配置usesCleartextTraffic或使用HTTPS
  • 如何解析JSON:Gson、Moshi、Fastjson的区别
  • 如何处理异常:网络超时、JSON解析失败、服务器返回非200状态码

4.2 布局优化:从一道界面代码题说起

笔试有一道题目是给一段嵌套了多层LinearLayout的布局,问有没有优化空间。优化方向比较明确:使用RelativeLayout或ConstraintLayout减少层级;用include复用布局;用ViewStub延迟加载不常出现的布局;用merge减少嵌套层级。

这里有个容易踩的概念坑:有人说LinearLayout层级越多越慢,于是全部换成RelativeLayout。实际上RelativeLayout在测量时会对子View进行两次measure,复杂情况下性能反而不一定好。LinearLayout配合weight虽然看起来嵌套多,但不等同于一定慢。优化布局的核心指标是减少measure和layout的次数,而不是机械地换控件。

实操心得:真实项目里我用ConstraintLayout写大部分页面,因为它能有效减少嵌套。但有些场景比如等分横向排列,用LinearLayout的weight反而更简单,也不会有性能问题。关键是你要能解释清楚为什么选择某种布局,而不是只会“套模板”。

4.3 JSON解析与数据容错:笔试不敢明说但一定会考的

直播业务里JSON是主要的数据交换格式,笔试会问JSON解析方案的选型,以及遇到特殊数据怎么处理。最常见的坑是:服务端返回的字段偶尔会缺失、类型不匹配、值为null。如果你用Gson做严格解析,一旦遇到未知字段或者类型错误就会崩。

处理方法有两个方向:一是使用Gson的@SerializedName注解对应字段名,用JsonReader做容错解析;二是设计通用的响应体包装类,比如Result 包含code、message、data三个字段,先判断code再解析data。笔试如果让你写一个网络请求的完整流程,你需要把线程切换、解析、错误处理都考虑进去,这才是完整的工程能力。

热词里那些file:///storage/emulated/0/android/data/...的路径也提醒了一点:Android 10之后分区存储正式落地,App能访问的外部存储目录受限。如果你做文件下载、照片选择这样的功能,以前直接读SD卡路径的方式行不通了,必须通过MediaStore或SAF框架。笔试如果问文件存储路径的选择,你需要能区分内部存储、外部存储私有目录、公共目录三种位置,以及访问权限的差异。

4.4 代码规范与R8混淆:被忽视的送分题

热词里有“android r8”、“谷歌android马甲包代码混淆”这些,说明很多人在关注代码混淆。笔试题里关于混淆其实常考几个知识点:混淆的原理是什么、proguard-rules.pro里keep的配置、为什么要keep住实体类(因为有Gson反射)、为什么要keep住四大组件和JNI方法。

R8是ProGuard的升级版,它不只是混淆,还做了压缩、优化、脱糖。热词里“android r8”应该是这个意思。笔试如果问你怎么保证release包的代码能正常运行,你需要答出:混淆规则要保留下哪些类不能被混淆,尤其是使用反射的地方。我见过不少开发者在线上遇到ClassNotFoundException,就是因为混淆时把带有反射调用的类名给改了。

实操心得:我的习惯是所有实体类统一放到一个包下,然后keep整个包。这样Gson和自定义View的反射调用都不会被混淆破坏,不需要逐条去写keep规则,省心很多。

5. 算法题实战:字符串压缩、数组处理与手写代码

5.1 字符串压缩题的完整解题思路

A卷里有一道字符串压缩的算法题,大意是把连续出现的字符压缩成“字符+次数”的形式,比如aabcccccaaa变成a2b1c5a3。如果压缩后没有变短,则返回原字符串。

这道题本身不难,但坑点很多:

  • 边界条件:输入空字符串怎么办?输入只有一个字符怎么办?输入所有字符都不同时,压缩后的字符串会比原字符串长,此时要返回原字符串
  • 字符计数:用StringBuilder拼接时,要注意数字转换成字符串的位置
  • 时间复杂度:如果每次拼接都直接用字符串加法,会产生大量临时对象,笔试代码不要求极致性能,但如果你能写出来用StringBuilder,就是加分项

下面是我推荐的解题模板:

public String compressString(String S) { if (S == null || S.length() <= 2) { return S; } StringBuilder sb = new StringBuilder(); int count = 1; for (int i = 0; i < S.length(); i++) { if (i + 1 < S.length() && S.charAt(i) == S.charAt(i + 1)) { count++; } else { sb.append(S.charAt(i)); sb.append(count); count = 1; } } return sb.length() < S.length() ? sb.toString() : S; }

这道题的考察重点不是算法多精妙,而是你会不会处理边界。很多同学能把主逻辑写对,但忽略最后一步“压缩后没有变短就返回原串”,丢分很可惜。

5.2 手写快速排序与时间复杂度的严谨表达

排序算法是笔试常客,A卷要求手写快排。快排的思路不复杂:选一个基准值,把小于它的放左边,大于它的放右边,再对左右子数组递归排序。但手写的时候最需要注意的就是递归终止条件和分区函数里的游标移动。

如果笔试要求输出排序过程和每次分区后的数组状态,你需要能模拟出来:第一轮分区之后,实际就确定了基准值的最终位置。输出时要注意格式,有的题目要求用空格分隔数字,有的要求换行输出,别在输出格式上吃亏。

另外,时间复杂度一定要准确:快排平均O(n log n),最坏O(n^2)。最坏情况发生在数组已经有序时,每次选的基准值都是最大或最小元素,导致分区极不平衡。面试官如果追问怎么避免,你可以回答随机选择基准值或者取三数取中,这个细节能体现你的算法功底。

5.3 链表环检测:快慢指针的边界处理

如果卷子里出了链表相关题目,多半会考环形链表检测。判断一个链表是否有环,用快慢指针:快指针每次走两步,慢指针每次走一步,如果存在环,两个指针一定会相遇。

public boolean hasCycle(ListNode head) { if (head == null || head.next == null) { return false; } ListNode slow = head; ListNode fast = head.next; while (slow != fast) { if (fast == null || fast.next == null) { return false; } slow = slow.next; fast = fast.next.next; } return true; }

这里的一个细节是:快慢指针的初始位置可以不同,但必须保证移动规则一致。如果初始都指向head,那么在循环里要先判断fast是否为null再移动。考算法的目的是看你的代码是否健壮,而不是只追求核心逻辑正确。

5.4 笔试算法的时间分配与答题顺序

算法题容易让人上头,但笔试的时间是有限的。我建议拿到卷子先花两分钟通读所有题目,把会做的先做掉,算法题留到最后。不要在一道题上死磕超过20分钟,尤其是选择题占比高的卷子,先把确定性高的分数拿到手。

如果最后时间不够,也要把思路写出来。笔试阅卷时,有时会看你的思考过程,哪怕没有运行通过,只要伪码思路清晰,也能拿到一定分数。真的不会做,就写最朴素的暴力解法,这比空着不写要强得多。

6. 备考建议:从笔试结束到真正拿到Offer的最后一公里

6.1 复习路线:校招Android岗的知识地图

如果你正在准备校招,可以参考下面这个优先级来安排复习:

第一优先级:Java基础(集合、并发、异常)和Android四大组件。笔试大部分题目都从这些核心点出发,围绕它们做变体和加深。

第二优先级:Handler消息机制、Activity启动模式、Fragment生命周期、ListView/RecyclerView缓存机制。

第三优先级:网络编程(HTTP、TCP、OkHttp、Retrofit)、数据库(SQLite、Room)、性能优化(内存、布局、启动速度)。

第四优先级:设计模式、算法与数据结构、Kotlin基础。

这套路线是我根据2018年欢聚时代和后来多家一线公司的笔试风格总结出来的。现在再看,方向依然适用,整体知识框架没有本质变化,只是Kotlin的占比变高了,协程也成了高频考点。

6.2 笔试之外的加分细节:代码风格与注释习惯

笔试除了看答案对不对,还会看你的代码风格和习惯。命名规范很重要,变量名不要写成a、b、c,类名方法名遵循驼峰命名;逻辑边界要清晰,异常处理要到位。这些细节往往就是大家分数拉开差距的地方。

注释也是一样,关键步骤写一行注释,标注你的思路,比如“// 当前位置之后不存在重复元素,直接返回“,会让阅卷人觉得你思路清晰。但不要满屏注释,核心步骤两三处就够。

6.3 我的经验之谈:笔试只是起点,不是终点

说到底,笔试考察的从来不是你对某个API的记忆,而是你有没有真正理解Android的底层机制。Handler为什么这么设计?四大组件的生命周期为什么是那个顺序?这些问题答得好,不只是笔试得分,更是你之后做开发的思维底座。

如果你在准备校招,我建议你不要只刷题,而是把每个知识点对应到自己做过的项目里去回想:我上次遇到这个问题是怎么解决的?哪里踩过坑?这样复习,知识记得牢,面试时也能讲出真实案例,比背诵标准答案有说服力得多。

祝正在准备校招的你旗开得胜。这套2018年的卷子今天拿出来复盘,依然能帮到不少人,希望这份拆解能少让你走点弯路。

http://www.cnnetsun.cn/news/4304709.html

相关文章:

  • 基于SpringBoot的消防知识学习平台系统微信小程序(毕设源码+文档)
  • 一句话生成学术级PPT:Codex CLI+DeepSeek+Beamer工作流
  • 十分钟跑起完整 Windows 11:Dockur Windows 容器完整上手
  • SAM 三个检查点怎么选:ViT-H / ViT-L / ViT-B 性能对比与选型完整指南
  • 编程停滞:LLM辅助开发下的能力退化与破解之道
  • 线上问医系统设计与实现:Spring Boot + MySQL全栈实战解析
  • Win11Debloat:Windows 11一键系统优化,10分钟告别预装软件与隐私追踪
  • PowerStep01 SPI写不进寄存器?步进驱动初始化失败排查全指南
  • whisper.cpp 模型怎么选:从 tiny 到 large-v3-turbo 的速度与准确率权衡
  • 老软件拯救:在Windows 11上运行1998年CD-ROM世界地图集
  • 3条命令在Docker容器里跑起Windows:dockur/windows完整指南 [特殊字符]
  • dockur/windows:在 Docker 容器中运行完整 Windows 系统的实操指南
  • Penpot 开源设计工具:基于开放标准的设计协作平台
  • 遍历性游戏Python模拟:期望正收益为何长期亏损?
  • Spring AI 2.0实战:从多模型到Agent的一周学习路线
  • 单片机电源管理:12V转5V转3.3V两级降压方案设计与调试
  • 分布式服务的自动巡检设计
  • 爱奇艺iOS校招笔试全复盘:核心考点、解题思路与备战策略
  • you-get -I 批量下载:一个文本文件搞定100条URL
  • 前端两年经验跳槽面经:从简历准备到高频面试题拆解
  • Magisk Root 完全掌握:从原理到定制的完整指南
  • Pandas入门指南:2小时掌握DataFrame数据清洗与分组聚合
  • 科学计算日常巡检的有效方法
  • 从老源码到现代API:接口设计、安全与实战全解析
  • Typst 快速上手:5 分钟从零编译出第一份 PDF 文档
  • VS2019+OSG+osgEarth+GDAL+Qt全链路编译指南:三维GIS开发环境搭建
  • 快速上手 whisper.cpp:把语音转文字搬回自己设备的完整指南
  • Starship 提示符提速:3 档方案把 500ms 压进 50ms
  • MRIcroGL完全上手:从DICOM转换到出版级脑图渲染
  • 用 Remotion 一个下午做出三语视频:React 视频国际化的完整实战