先量一遍,再决定删什么
几乎所有改包的人,都会在某个时刻盯着那个几十兆、上百兆的文件想一件事:里面到底装了什么,为什么这么大。如果是要发给现场、走移动网络、或者要塞进一个体积有限的分发渠道,这个问题就从「好奇」变成了「必须解决」。
而答案往往比想象中集中:包里的体积,八成压在三个地方。不是均匀分布的五十个目录,而是三处大头,每处都能用一句话说清它为什么占地方。
这篇文章讲清三件事:体积到底压在哪儿、哪些能删哪些不能删、以及为什么「删了会变快」这个说法多半是错觉。最后一条比前两条重要,因为它决定了你会不会在错误的地方花力气。
只需说话,就能让应用变成你想要的样子。而在「安卓修改大师智改工坊」里,包里的目录结构是能直接看到的——反编译之后哪个体积大、哪个是重复的,一眼就能看出来。先看清再动手,是这个话题里最省时间的一步。想先看看一个包的内部构成,可以从 https://www.apkeditor.cn/ai-version.aspx 下载智改工坊,反编译之后按大小排一下序。
一、先量,别猜
这个领域的第一个错误动作,是凭印象猜「大概是图片太多了」或者「大概是代码太肥了」,然后照着猜的方向删。
正确的第一步只有一件事:把包解开,按体积排序,看前五个是谁。这个动作一分钟,它能直接告诉你答案,而且答案常常和直觉不一样——很多人以为是图多,实际上一看,一个从来没注意过的目录占了三分之一。
排序的时候要注意一件事:看的是「解开之后的体积」,不是「包里的压缩体积」。两者差别很大。图片本身就是压缩格式,再压一遍几乎不变;而代码和数据这类文本性质的内容,压前压后可能差三倍。所以按压缩后的体积排,会低估文本类目录的占比。
一个典型的中等规模应用的构成,大致是这样的比例:原生库占到三到五成,图片资源两到三成,代码一成多,剩下的零散。如果是游戏或者带离线识别、音视频处理能力的应用,原生库的占比会更高,可能到六七成。
这个比例不是让你背下来的,是让你有一个对照。如果你手里的包排出来完全不是这个形状——比如某个 assets 目录占了一半——那说明这个应用有它自己的特点,值得先弄清楚那一块是什么,再决定动不动。
二、第一处:原生库,一份代码变四份
原生库这个名字听着陌生,换个说法就清楚了:用 C 或者 C++ 写的、编译成机器码的那部分代码。它不在代码目录里,而在一个单独的目录下,文件名以 .so 结尾。
这一块为什么占地方?因为同一个功能,要为不同的处理器架构各编译一份。常见的四种架构,就是四份。而每一份都是完整的机器码,没法共用。
更麻烦的是,多数应用其实并不需要四份。现在市面上绝大多数手机用的是其中两种架构,另外两种只在很老的设备上出现。如果你的目标设备是近五年的机器,那两份几乎永远不会被加载。
于是这里就成了最明确的一处可优化空间:去掉两个用不上的架构,体积能直接降一大块,而功能一点不受影响——只要你的目标设备确实不包含那两种架构。
但这一步有个前提必须确认:这个应用里到底有几个原生库,它们分别是谁提供的。有些是应用自己的核心功能,有些是第三方组件带进来的(比如某个音视频处理库、某个图像识别库)。后者的情况更复杂——你可能不知道它有没有在某个角落被用到。
判断方法:先看文件名。以自家项目名或者核心模块命名的,多半是自家的;名字像某个第三方产品的,去查一下它是干什么的。这一步花十分钟,能避免删掉之后某个功能在特定场景下失效——而那种失效往往要等到用户反馈才会被发现。
三、第二处:那个叫 assets 的抽屉,什么都能往里塞
assets 是包里一个很特殊的目录。它没有任何规则——不是图片、不是布局、不是配置文件,就是一堆原样的文件,由程序自己在运行时按名字去读。
正因为没有规则,它成了最容易被塞满的地方。见过的内容有:离线词典、语音模型、地图瓦片、字体包、演示视频、内置的网页、几套模板、几份样例数据。这些东西有个共同点:单个可能不大,加起来惊人。
它还特别容易留下历史包袱。一个功能下线了,代码删了,但当时为它准备的几十兆数据还躺在 assets 里,没人记得要删。这类「没人用的东西」是瘦身时最安全也最容易见效的目标。
怎么找?按体积排序,看前五个。然后对着最大的那个问一句:这个东西现在还有功能在用吗?如果答不上来,就去代码里搜它被读取的地方——通常是按文件名读的,搜那个文件名就能找到引用。
搜不到引用的,基本可以确认是历史遗留。搜得到引用的,再顺着看那个调用点有没有被走到——有的功能代码还在,但入口已经被隐藏了,这种情况下它同样是「活着但不被用」。
一个具体的例子:自家一个内部学习端,assets 里有一整套课程封面图,加起来四十多兆。看起来很正常,但看代码发现读取它们的那个模块已经不在任何入口里了——那是两年前一个版本的首页样式,后来改版就废了。删掉之后包小了四成,功能一点没少。
这就是 assets 的特点:它不会自己暴露问题。图片多,你能在界面上一张张看到;assets 里的东西可能永远不会出现在界面上,所以也不会有人提醒你它还占着地方。
按解开后的体积排序,答案通常很集中
四、第三处:一张图,四个尺寸
图片这一块的问题,上一篇讲资源索引表时提到过一半:同一个名字下面有好几份,为不同屏幕清晰度准备。
这在体积上意味着什么?意味着你以为只有一张图,实际上有四张。而且不是简单的小图变大图——四份加起来的体积,往往是单份的三倍多,因为最高清那份本身就比中号大好几倍。
于是「图片占了两三成」这件事,换算过来就是「最高清那份加它的三个兄弟占了两三成」。如果这个应用的图片主要是背景、插画、横幅这类大面积图,这个比例还会更高。
能做的优化有两类。第一类是压缩:把 PNG 转成体积更小的格式,或者用更高效的压缩参数重新导出。这一类不需要改任何引用,只换文件内容,风险最低,收益通常在图片体积的一到三成。
第二类是减少份数:去掉用不上的低密度那几份。这一类收益更大,但风险也更大——低密度设备会拿不到匹配的那份,退而用高清图缩小,效果能看,但内存占用上去。如果这个应用要在老设备上跑,不建议这么做。
还有一类常被忽略的:那些「改完之后留下来」的旧图。换图的时候如果没覆盖原文件,而是新加了一个,那两张都在包里。这种情况在多人协作、反复改版的项目里很常见。排查方法:找那些名字很像、内容也像的图,看是不是同一张的新旧两版。
这一类优化的共同点是:它需要逐张判断,没法批量。所以它的性价比往往不如前两处——原生库去掉两个架构是五分钟的事,图片压缩可能要一整天。做瘦身的时候,顺序应该按「收益除以工作量」来排。
五、第一个实例:从九十兆到六十兆,动了三处
自家一个设备巡检端,装在现场的手持机上。因为现场要走移动网络下载更新包,九十多兆的体积成了一个实际问题——有些地方的网络,下载一次要十几分钟,中途断了还得重来。
目标:砍到六十兆以内。这个目标不算激进,按前面的比例估算,三处各动一点就够了。
第一处,原生库。这个应用里有两个第三方库带了自己的原生库:一个做二维码识别,一个做图片压缩。每个都有四个架构的版本,加起来四十多兆。查了现场手持机的型号,都是近三年的机器,用的架构只有两种。删掉另外两个架构的目录,直接省下二十兆左右。
这一步的风险在于「万一有台老设备」。所以做完之后没有直接全量发,而是先发了一个小范围,让两三个点位用了一周。一周内没有反馈,才全量。
第二处,assets 里的离线包。这个应用带了一个离线的行政区划数据包,八兆多。查代码发现,只有在完全断网、并且要新建巡检点的时候才会读它。这个场景确实存在,所以不能删。最后的处理是把它换成了压缩后的版本——读取的时候多一步解压,省了五兆。
第三处,图片。把首页那几张背景图重新导出,用更高效的压缩参数,画质几乎看不出差别。这一处省了六兆多。顺带清掉了十几张「名字带旧版本号、实际上已经没有引用」的图,又省了两兆。
合计下来,从九十二兆降到五十八兆。三处的工作量分别是:原生库半小时、assets 两小时(要确认那个断网场景)、图片一下午(要逐张看)。
这一轮里还有一个没被写进账的成本:每一处改动都要重新走一遍装机验证。三处改动就是三轮验证,每轮十几分钟。而如果一开始就把三处一起改完再验,出了问题你根本分不清是哪一处——那个代价要大得多。所以这半小时、两小时、一下午的时间,有一半其实花在验证上,而不是花在改上。
这次的经验是:收益最大的那一处,工作量最小。原生库那一刀砍掉二十兆,只花了半小时;图片那一处花了半天,省了八兆。这个对比说明做瘦身必须先量后做——如果一开始就从图片开始,可能花两天也达不到目标。
六、第二个实例:删掉一个目录,两天后功能坏了
这个例子讲的是瘦身的另一面:删错了会怎样。
自家一个内部培训端,体积不大,二十几兆。为了给一个新模块腾地方,顺手清了 assets 里一个叫 sample 的目录,里面是十几段示例音频,五兆多。判断依据很简单:名字叫 sample,看起来就是示例素材,界面上确实也没见过。
发出去之后三天,客服那边收到一个反馈:某个课程里的「听读练习」功能,点进去是空的。
查下来才发现,那个功能用的是 assets 里的一段标准音做对比基准,而那段音就放在 sample 目录里。界面上不显示它,是因为它只被用来做比对,播放的是用户自己录的那一段。
这件事的问题不在技术,在判断依据。「名字像示例」和「确实没被用到」是两件事,而我们只做了前者。
正确的做法是:删之前,在代码里搜一下这个目录名或者其中的文件名。如果搜到了,就顺着看那个读取的地方是干什么的;如果搜不到,再确认一遍是不是通过别的名字间接读的(有些代码会把路径拼出来,搜不到完整路径)。
这个动作花的时间不到五分钟。而那次返工的代价是:重发一个包、让现场更新、解释一遍、以及后面每次瘦身都要多犹豫一下。
这个例子还有一个后续:从那以后,这个项目的瘦身改成两个人做——一个人列清单,另一个人独立核对每一项「确认没引用了吗」。核对的人不需要懂技术,只需要问「你怎么知道它没被用」。这个问题能把大部分「看着没用」的项筛出来。
七、能删与不能删:一张按类型分的表
把包里常见的东西按类型列一遍,标出「通常能删」「要看情况」「别动」,比记具体目录名有用得多。
| 类型 | 结论 | 前提 |
| 用不上的处理器架构的原生库 | 能删 | 先确认目标机型不包含这种架构 |
| 名字带旧版本号、已无引用的图 | 能删 | 删前搜一次名字确认 |
| 已经下线功能的 assets 数据 | 能删 | 搜不到引用才删 |
| 重复的两份同名资源 | 能删其中一份 | 保留条件更通用的那份 |
| 低密度的那几份图 | 看情况 | 老设备多就不要删 |
| 第三方库自带的多余语言包 | 看情况 | 确认不需要那几种语言 |
| 签名相关的几个文件 | 别动 | 删了装不上 |
| 资源索引表 | 别动 | 删了一启动就崩 |
| 清单文件 | 别动 | 改坏了一装就报错 |
| 代码目录里的任何文件 | 别动 | 这是改包的主战场,不是瘦身对象 |
这张表里最值得看的是最后三行。「别动」这三类是包能装、能跑的底座。瘦身的时候最怕的就是「反正看不懂,删了试试」——那三类删任何一个,包都会直接不可用,而且现象往往看不出原因。
中间两行「看情况」是最花时间的。它们的共同点是:删了也能跑,但某些设备或者某些场景下会变差。这类决定没有标准答案,取决于这个应用要装在什么设备上、给什么人用。做决定的人应该是了解使用场景的人,不是执行操作的人。
还有一条不在表里的经验:一次只动一类。别在同一轮里既删原生库又删图片,因为万一出了问题,你不知道是哪一类引起的。一次一类、装一台机器、走一遍主要功能,这个节奏看起来慢,但它让每一次改动都是可归因的。
八、为什么「删了会变快」多半是错觉
瘦身的时候最常听到的一句话是「包小了,跑起来也会快一点」。这句话在多数情况下不成立。
原因在于:应用运行的时候,不会把整个包加载到内存里。它按需去读——打开哪个页面就读哪个页面的资源,用到哪个库就加载哪个库。包里那些永远不会被读到的文件,对运行速度没有影响。
真正会影响速度的是两件事。一是启动时要加载的东西有多少——首屏的资源、初始化时的类、启动时就要加载的原生库。这些确实越少越快。二是运行时的内存占用——这跟图片的尺寸有关,跟包的大小无关。
所以「删掉两个用不上的架构」这件事,对运行速度的影响接近于零,因为那些库本来就不会被加载。它带来的收益是下载快、安装快、占存储少——这三点已经足够有价值,不需要再加上「运行快」这一条不实的。
反过来,有一个操作确实能让运行变快:把过大的图片换成尺寸合适的。一张四千像素宽的图显示在一个小卡片上,解码之后占的内存是它的好几倍。这类优化对老设备的流畅度影响明显——但它的收益来自「尺寸」,不来自「体积」。
还有一个相关的小现象:把包压小之后,有些人反馈「感觉变流畅了」。这多半是真的,但它来自另一条路径——包小了,安装的时候解压和写入的工作量少了,首次启动的准备时间也就短了。这是「安装过程变短」,不是「运行时变快」。这两件事在体感上很像,但改法完全不同。
分清这两件事很重要,因为它决定了你的验收标准。如果目标是「下载快」,验收就看包的大小;如果目标是「运行快」,验收要看启动时间和内存占用,而那需要另外一套方法。用包的大小去证明运行变快,是拿错了尺子。
九、七个问题,都是瘦身时真被问过的
一、我不知道哪些能删,能不能先删一半试试?
不建议。「删一半试试」的后果是不确定的:可能包还能跑,也可能在某个冷门功能上崩。更稳的做法是先删「明确用不上」的那一类,比如多余的处理器架构——这一类的判断依据是硬性的(目标机型用什么架构),不靠猜。
二、原生库删了架构,会不会在某些手机上装不上?
不会装不上,会「装得上但用不了那个功能」。系统在安装时不会因为缺少某个架构而拒绝;真正的问题是运行到需要那部分代码时找不到,直接崩。所以判断标准不是「能不能装」,而是「目标设备有没有那种架构」。
三、图片换成更小的格式,画质会差很多吗?
取决于换什么格式、压到什么程度。同一个画面,用更高效的编码、参数调得合理,肉眼看不出差别的压缩比通常在三四成。关键是别一次压到底——先压三成,装上看,觉得没问题再压一点。压过头之后画质是不可逆的。
四、删掉的语言包,会不会让某个用户看到空白?
会,如果你删的是他用的那种语言。语言包这块要格外小心,因为你无法预知用户设的是什么语言。如果要删,只删那些明确不可能有用户的语言(比如某个完全无关的地区语言),而且要保留通用那份作为兜底。
五、为什么有些包解开之后比下载的还大?
因为包里的内容大部分是压缩存放的,解开之后自然是膨胀的。图片本身已经是压缩格式,解开前后差别不大;代码和数据这类文本,解开后可能大两三倍。所以量体积要看解开后的数字,那才是真实的资源占用。
六、改完之后包小了,但装上之后占的存储没少那么多,为什么?
因为占存储是「解开后的体积」加上运行产生的数据,不是下载的那个数字。包的大小影响的是下载和安装那一下,装载之后占多少看的是内容本身。这也是为什么「删掉用不上的架构」能明显减小下载体积,但对已安装占用的影响没那么大。
七、分卷包是不是就一定比单个包大?
不一定,但它更容易变大。分卷包把内容按设备特征拆成几份,每份只带自己需要的那部分,理论上更省。问题在于很多分卷包实际上每份里都放了一份公共资源,加起来反而更大。判断方法:把各份解开,看公共资源的目录是不是重复出现。
十、三步:量、列、删
把这一篇的做法压成三步,每步都有明确的产出。
第一步,量。把包解开,按体积排序,记下前五名和它们的体积。产出是一张五个条目的清单,加上「这个包一共多大、目标是多少」。没有这张清单就开始删,等于蒙着眼睛走。
第二步,列。对着前五名,每一项写两句话:这是什么、还有没有功能在用它。产出是一张判断表,每项后面标「能删」「看情况」「别动」。这一步不看体积,只看性质。
第三步,删。按「收益除以工作量」排序,从最划算的那一项开始。一次只删一类,删完立刻打包、装机、走主要功能。一轮通过再进下一类。
三步的产出物加起来就是一张纸。但这张纸的价值很高——下次再有人问「这个包能不能再小一点」,你不需要从头量一遍,看一眼那张纸就知道还有哪些空间。
三步做完之后,最好再做一件事:把结果和开头那张清单对一遍。目标是八十兆,现在是七十五兆,差的那五兆是怎么来的;前五名里哪一项的体积变了、变成了多少。这个对账动作五分钟,但它能让你确认「省下来的每一兆都是自己删的」,而不是碰巧。
还有一个容易被忽略的第四步:把删掉的东西记下来。不是为了将来恢复,而是为了将来解释——半年后有人问「为什么这个功能在某些设备上没有」,你能立刻回答「因为我们去掉了那种架构」。没有这份记录,同一个问题会被重新讨论一遍。
收益最大的一刀,往往也是工作量最小的一刀
十一、按「收益除以工作量」排一遍,顺序就清楚了
前面说过要按性价比排序,这里把它具体化成一张表。数值是大致量级,用来说明相对关系,不是精确承诺。
| 动作 | 省多少 | 工作量 | 风险 |
| 去掉用不上的处理器架构 | 很大(一到三成) | 半小时 | 最低,只需确认目标机型 |
| 删除重复的素材目录 | 大(取决于重复程度) | 一到两小时 | 低,确认两份是同一批 |
| 清理已下线功能的数据 | 中大 | 一到两小时 | 中,要确认引用 |
| 图片换更高效的编码 | 中小(一到三成) | 半天到一天 | 低,画质要逐张看 |
| 删掉多余的语言包 | 小 | 一小时 | 中,要确认没有用户在用 |
| 去掉低密度的那几份图 | 中 | 两小时 | 较高,老设备可能受影响 |
| 合并小文件、重排目录 | 小 | 很长 | 高,可能触发编号问题 |
这张表的读法是:从上往下做,做到目标就够了,不要做完全部。前两行的性价比明显高出其他,而它们恰好也是最容易被忽略的——因为大多数人一听到「包太大」,第一反应是去压图片。
最后一行基本上不该做。合并小文件、重排目录这类动作,省下来的体积很小,但会改变包的结构,牵动资源编号。前面讲过编号位移的后果,那种问题查起来极其困难。凡是「重组结构」的优化,都要单独评估,不能和「减少内容」混在一起做。
还有一个不在表里的动作值得单独提:确认那些「体积最大」的东西是不是真的需要这么大。比如一张背景图,实际显示区域只有屏幕的一半,却按两倍屏幕尺寸导出;比如一个离线数据包,实际上只用到了其中三个字段。这类问题不是「删」,而是「本来就不该这么大」——它们的收益往往比表里任何一项都大,但要有人愿意去看内容本身。
十二、五个听着有道理、其实会害了你的做法
瘦身这件事,做错的方式比做对的方式多。下面五个做法都见过,而且都有人在用。
第一个:先把最大的文件删掉看看。最大的文件往往是核心素材或者主库,删了十有八九直接崩。正确的顺序是「按类型判断」,不是「按体积判断」——体积只决定优先级,不决定能不能删。
第二个:把所有图片统一压到很低的质量。这样确实能省很多,但界面上的观感会整体下降。而且这种下降是全局的,用户一眼就能看到。更稳的做法是只压那些大面积、非关键的图(背景、插画),把界面元素和小图标留着。
第三个:删掉那些「从来没见它显示过」的资源。这些资源可能被用在很偏的路径上——错误提示、空状态、某个只有管理员能进的页面。「没见过」不等于「没被用到」,这一点前面那个音频的例子已经说明了。
第四个:为了省事,把两个目录合并成一个。合并会改变目录结构,可能触发资源编号重排,而重排带来的连锁问题很难查。瘦身的原则是「只减少,不重组」——减少是线性的,重组是不确定的。
第五个:一次改完,一次发。把所有优化攒在一起,打一个包发出去。这样万一出问题,你要在五六处改动里挨个排除。一次一类、一轮一验,看起来慢,但它让每一次改动都有明确的因果。
这五个做法的共同点是:它们都试图用「批量」和「省事」来加速。而瘦身这件事恰恰不适合批量加速——因为它的风险不在操作上,在判断上。判断错了,做得越快,返工越大。
一次一类、一轮一验,让每次改动都能归因
十三、什么时候其实不该做瘦身
这一节是给「已经决定要瘦身」的人踩一脚刹车。因为有些情况下,瘦身带来的麻烦比收益大。
第一种,这个包马上要发,而且改动很小。这时候动体积意味着要重新走一遍完整验证,而验证的成本可能高于省下来的那几兆。瘦身应该有自己的时间窗口,不要夹在一个紧急需求里顺手做。
第二种,你不知道这个应用装在什么设备上。如果它面向的是一批不确定的、可能很老的设备,那去掉低密度资源、去掉老架构都会带来实际风险。判断不了使用场景,就不要做需要「判断设备」的优化。
第三种,这个应用已经不打算再发版了。如果这一版就是最后一版,那省下来的下载体积只影响一次,而风险却要承担一次。收益一次性、风险一次性的事,值不值得做,要看这一版的重要性。
第四种,包的大小根本不是当前的瓶颈。如果分发走的是内网、或者用户根本不在意多等十秒,那瘦身的价值就很低。先确认「大」这件事真的造成了困扰——是下载失败率高、还是安装时间长、还是存储告警,有一个具体的痛点再动手。
这四条不是让你不做,是让你先确认「为什么要做」。有明确理由的时候,前面那些方法才有意义;没有理由的时候,它们只是在消耗时间。
一个实际的判断方法:如果有人问「为什么这个包这么大」,你能一句话答上来吗?答不上来,说明该做的是「量一遍」,不是「删一轮」。量完之后你可能发现,最大的那块是必须的,而「大」只是一个感觉。
十四、一次返工的完整账:省了八兆,赔了两天
把前面零散提到的东西串成一次真实的返工,看看代价是怎么积累起来的。
需求:一个自家内部使用的仓储端,包一百二十兆,现场抱怨下载太慢,要压到八十兆以内。
第一轮,一天。按体积排序,第一大是原生库,五十五兆;第二是 assets 里的图片素材,四十兆;第三是代码。判断很直接:原生库去掉两个架构,assets 里压缩图片。一轮下来到了一百零二兆,离目标还差二十多。
第二轮,半天。回头看 assets,发现里面有一个叫 temp 的目录,十二兆。名字看着像临时文件,且没有任何代码引用它(搜了目录名、搜了几个文件名,都没搜到)。删了。到了一百零九兆——等等,比上一轮还大?
这里出了第一个错:两轮之间我们改了别的东西,包反而变大了。原因是那半天里顺手加了两张新的引导图。这就是「没有单变量对比」的代价——你无法判断上一步到底省了多少。
第三轮,一天半。把新加的图撤掉,重新打包,九十八兆。然后再砍:低密度图片删掉,去了六兆;几个语言包删掉,去了三兆。到了八十九兆。还是没到八十。
第四轮,发现问题。在翻 assets 的时候,发现有两大块内容几乎一样:一块叫 images,一块叫 img。打开看,是同一批素材的两份拷贝,一份是两年前的命名,一份是去年的。删掉旧的那份,去了十四兆。
最终七十五兆,达标。但整个过程花了四天。而如果一开始就把「重复的内容」也列进排查项,这个活在第二天就能结束。
这次返工的三个教训:一是每轮只改一件事,否则无法归因;二是排查项里要加一条「有没有内容几乎一样的重复目录」;三是目标要一次说清,别一边压缩一边又加新素材。
这个案例里还有一个细节值得说:那两块重复目录之所以存在,是因为两次改版用了两套命名习惯。第一年叫 img,第二年的开发习惯写 images,交接的时候没人提起旧的那批已经不用了。这种情况在「同一个应用换过几茬人」的项目里非常普遍。如果一开始就按「内容相似度」查一遍,这两块会在十分钟内被认出来。而在「安卓修改大师智改工坊」里,反编译之后目录是完整摊开的,两个名字相近、体积相近的目录放在一起,一眼就能看出问题。
最后补一句关于目标的:瘦身的目标应该是「够用」,不是「最小」。八十兆达标就停,不要去追七十兆。因为越往后做,能删的越少、风险越大——而收益从「下载快一半」变成「下载快十秒」,用户根本感觉不到。知道在哪儿停,是这件事里最难也最省力的一部分。
第四条最容易被忽略。因为加素材和删素材往往不是同一个人做的,也不是同一时间做的。瘦身期间,这个包应该冻结其他改动——否则你永远在和一个移动的目标比体积。
十五、把这件事教给别人,三句话就够
瘦身这件事,讲原理容易讲成技术课。给三句话,对方就能上手。
第一句:先量再删,量完按大小排。不量就删,等于闭着眼睛挑东西扔。
第二句:按类型判断能不能删,不按大小判断。最大那个往往不能动,第十大那个可能一文不值。
第三句:一次只删一类,删完立刻装一台机器走一遍。攒着一起删,出了问题你不知道是哪一类。
三句话之后补一句提醒:删之前搜一下名字,搜不到引用才删。这一句能挡掉大部分「看着没用其实在用」的误删。
这四句话覆盖了这一篇的大部分实用内容。剩下的——四种架构各是什么、图片怎么压、分卷包怎么处理——属于具体动作,遇到的时候查一下就行,不需要提前记住。
十六、那些年被塞进包里的奇怪东西
清 assets 清得多了,会看到一些让人愣住的目录。列几个真实见过的,不是为了好玩,是因为它们说明了一件事:包里的体积,很大一部分是「当时的顺手」留下来的。
一个装了两年的演示视频。十二兆。是上线前给客户看效果用的,放在一个叫 demo 的目录里。上线之后没人记得删,播放它的代码也早就没了。
一整套设计稿的分层导出。三十多兆。设计师交付时把整个导出目录打包发过来了,开发直接扔进了 assets,只用了其中三张。剩下那几百张,每一张都完整地躺在包里。
三个版本的字体包。每个九兆,一个正常体、一个粗体、一个细体。而界面里只用了正常体——粗体是代码里加粗实现的,不需要单独文件。
一份两年前的地区数据。八兆。数据已经更新过两次,但旧的那份没删,新的那份放在了另一个名字下面。两份都在包里。这就是前面那个返工记录里提到的「重复目录」,它比我以为的常见得多。
一个空的日志目录,里面只有一个空文件。零字节,不占地方,但它让排查的人多花了五分钟去确认它是什么。这类东西的价值是负的——它不占体积,但占注意力。
这些例子的共同点是:没有一个是「故意放进去的垃圾」,每一个都是当时合理、后来忘记的决定。所以清 assets 的时候,别带着「谁这么干」的情绪——这些包是很多人一起做出来的,每个人放进去的东西在当时都有理由。
这些例子里最值得记住的是第二个。「交付目录整个扔进去」这个动作,一次就能造出几十兆的垃圾,而且它看起来完全不像垃圾——那是一个整洁的、由设计师精心分层的目录。区别只在于,其中绝大部分从来没有被程序读过。所以判断标准永远只该是「有没有被读到」,而不是「看起来像不像有用的东西」。
实际操作上,这给了一个很有用的启发:清理的时候按「最后修改时间」排一遍。三年没动过的目录,和上个月刚加的目录,性质完全不同。前者大概率是历史遗留,后者大概率还在用。时间是一个比名字更可靠的信号。
十七、用过的人怎么说
"我们那个包一百二十兆,一直以为图太多。排序一看,原生库占了一半。去掉两个架构,直接少了三十多兆,功能一点没变。"
—— 小吴 · 一家设备服务公司的技术负责人
"删过 assets 里一个叫 sample 的目录,五兆。三天后有个功能空了,才发现那是它的比对基准。现在删之前一定先搜一遍名字。"
—— 阿凯 · 一家物流公司的信息化专员
"以前我以为包小了运行就快。后来才知道运行的时候不会加载整个包,那些删掉的东西本来也不会被读到。包小只影响下载和安装。"
—— 周工 · 一家设备制造企业的技术主管
"最容易忽略的是重复目录。我们包里有 images 和 img 两份,内容几乎一样,一份两年前的、一份去年的。删掉旧的去了十四兆。"
—— 林工 · 一家制造企业的信息化主管
"现在我会把瘦身和别的需求分开做。上一次一边压缩一边又加了新素材,最后算不清到底省了多少,白绕了两轮。"
—— 小徐 · 一家教育培训机构的教务
五条反馈对应五件事:先量再删、删前搜引用、包小不等于跑得快、重复目录要单独查、瘦身期间要冻结其他改动。而这五件事,正好是这一篇的五节。
第三条那句"包小了运行就快",是这个话题里流传最广的一句误解。它不是完全错——启动时加载的东西少了确实会快——但它把两件不同的事混成了一件。分清之后,你会发现很多瘦身的收益其实在下载和存储上,而这已经足够值得做,不需要再借一个「更快」的名义。
合规提醒
本文讨论的所有改动,都应在自己拥有版权、或已获得权利人明确授权的应用上进行。请勿用于破解他人软件、绕过授权验证、去除版权标识或任何侵犯他人权益的用途。文中的巡检端、学习端与仓储端,都是我们自家开发、授权给内部和合作门店使用的应用。关于素材还有一句:瘦身的时候最容易做的动作是删别人的东西。包里那些图、字体、音频,很多是有授权的商业素材。删之前最好确认一下它的来源——有些授权要求保留署名,删掉文件的同时也删掉了署名,那是另一个问题。
安卓修改大师智改工坊
先看清体积压在哪儿,再决定动哪里
反编译建项目 → 目录按大小排序 → 逐类判断 → 一次一类验证
官网 www.apkeditor.cn
立即下载智改工坊(AI 版)
支持 apk / apks / xapk / apkm 等包型 · Windows 桌面端
只需说话,就能让应用变成你想要的样子。而在"包太大"这件事上,这句话背后还藏着一句提醒:说清"压到多少兆"之外,最好再说一句"别动那几个必须的"。剩下的交给安卓修改大师智改工坊——反编译之后目录结构摊开在你面前,哪块大、哪块重复,先看清再动手。