2021-10-23

21 篇热帖

1. 新 MacBook pro 开箱
2. 千万别看沙丘

别看沙丘 别看沙丘 别看沙丘 前期宣发吹上天,实际就一彻头彻尾烂片

都有高科技星际殖民了,结果在那刀战,甩飞镖?? 全片在玩灵性,剧情拖沓没有起伏,看完还是不明所以. 片尾来了就"It's just beginning" 感觉第一部就要被喷成 ending 了

千万别看,浪费宝贵的两小时生命

3. 新款 MacBook M1 Pro 16 真机上手视频
&t=19s
4. 程序获取手机指定号码的短信
目前接手了一个自动化项目,其中有个步骤涉及到手机短信验证码的校验,目前都是人肉接收短信后再手动填入到程序中去,非常麻烦,所以在想这样的一个方案:

1.该号码为专用,平时只会相关的验证码,本身没有其他使用;

2.采用一个 [开源程序] ,把手机管理起来(手机可以长期插着电脑),每次收到短信之后会自动根据号码和关键字筛选,并通过 API 方式对内部提供

3.主程序通过该 API 获取从而实现自动化

因此想咨询一下,是否存在比这更好的方案,或者有没有这个 [开源程序] 的推荐,非常感谢

声明:文中提到的自动化项目非违法的数据爬取等类似的项目
5. 程序员 5 年坚持制作免费教程造福百万学生

标题为微博热搜看到,此人 B 站:/165659472 ,虽然我不是程序员,简单了解下值得竖大拇指👍🏻,不知道 V 站有没有他账号。

6. 各位平时文件同步用哪个?
7. 小米 11pro 8+256 3799 怎么说 值得入手么

求比较 11Pro 11U mix4 优劣

8. 不知道明年三月份会不会发布新的 mac air,现在买是不是 49 年入国军呀

好纠结啊~这次没有发布新的 mac air,又不知道明年 3 月份能不能出新的 air,现在到底是不是入手的好时机呢?大家帮我参谋参谋

9. Genius Bar 极为离谱的工作失误

我有个朋友在 2019 年底买了一台 16 英寸的 MacBook Pro,显卡升级到了 5500M 8GB

img

之后电脑出现问题去天才吧维修,给换了主板,整个过程并没有什么问题

img

不过维修完后又出现了问题,所以再次去天才吧,这次也是给换了主板,应该是解决了问题

img

然而这次维修的更换记录显示,更换的主板搭载 5500M 4GB,也就是说天才吧把他的电脑“降级”了

更为离谱的是,我这个朋友在维修之后使用了这台电脑一年半居然没有发现他的显存变少了。直到最近几天他给我发了第一次维修的更换记录又提到他的电脑是 4GB 显存的,我发现有那么一捏捏的不对劲之后,才发现天才吧出现了失误。

目前 Apple 那边的回应是可以退还升级显存的 750 元,不过只能用于 Apple Store 购物。

10. 对帖子的补充与终结 [现在在 github 开源项目上不回答别人的问题,都是错了么]

原文链接: [开撕] 现在在 github 开源项目上不回答别人的问题,都是错了么?并且还是错的很严重的那种么?

我是这边篇文章的发帖人,昨天我实在太过气愤,只想在 v2 上找个公道,因为除了 V2 我也不知道在哪找个公道。

发了文章后,经过了一个晚上的冷静,大家也都在支持我,现在公道找回了,气也消了,还有很多 v 友都到 github 支持我,这里我非常谢谢大家。

我听了大家的建议,github 和 v 站都把他 block 了,今天是周末,希望大家都有个愉快的周末,多陪陪家人,不要再因为我这件事浪费大家的宝贵时间。

从这件事,我也得出了几个反思,与大家分享下:

  • 第一点也是最重要的一点,个人隐私问题。建议大家在 github 或者博客获取其他的社交媒体上,不要留摸索能找到个人通讯软件的东西。例如:QQ 邮箱之类的。若果要用 QQ 邮箱,v 友们推荐说有 QQ 邮箱的马甲:foxmail 之类的。

  • 搞技术的人,遇到不懂的问题,先要 Google 或者 stackoverflow,很多博客已经写的很好了,花点时间看下,然后再对比下源码,一会就能找到答案。

  • 我最开始搞 Android 时,看别人的文章也遇到很多问题,但是我都不去打扰,实在不懂的话,我都是先留言说:你好,我能不能请教下问题。突然加别人微信或者 QQ 真的很唐突,正常人都会觉得冒犯。

  • 遇到不礼貌的人、价值观不同的人,趁早拉黑、block,gitbub 我玩的不太多,昨天第一时间没找到能 block,后面还是 v 友教的。

  • 写文章不容易,开源项目也不容易,用心维护公众号的人也不容易,别轻易诋毁,有质疑,大家礼貌交流,如果这些人都被骂走了,技术圈就变成了饭圈了。

最后,真心谢谢大家,祝大家周末愉快!

11. 家里两个小米路由器组 mesh,次路由速度很差,希望得到优化建议

现在在用小米的 ax3600 和 ax1800 组了个 mesh ,但是 ax1800 作为次路由的信号非常差,主要是主路由和次路由的距离可能太远了。 在网上找了个和我家比较类似的户型做了个示意图在下面。

因为高通芯片供应的原因,ax3600 和 1800 都很难买到或者价格非常高。看了一眼咸鱼,应该可以按我的购入价出。

请教一下各位,我现在的情况应该是再买一个小米或者红米的型号作为补充呢?还是说全套换个 TP-LINK 之类的东西比较好? 我的主要诉求是希望主卧( ax1800 所在的房间速度可以好一些)

先谢谢各位

路由器位置测速情况

12. 看了新 MBP 的上手视频,反而能接受刘海了,毕竟能把顶部菜单栏改成黑色背景隐藏刘海,应用全屏也不会延伸到刘海,这种刘海区域直接给多做一截屏幕出来的思路不错,交互上甚至比以前更舒服了。

而且以前应用全屏时候,只要光标触到屏幕顶部,菜单栏就会弹出来,然后有的时候就会带动应用内容顶部工具栏下移、或者遮住应用的顶部内容。 现在新 MBP 光标上移触到顶部,只是菜单栏按钮显示出颜色,刘海仍然因为整个菜单栏背景是黑色的,而不明显。 而且因为应用内容根本不延伸到刘海区域,也就没有应用工具栏被带动下移,或内容被遮住的问题,交互上反而是个进步了。

13. 每日负:我为什么讨厌亲戚,以及拒绝和他们谈论我的私事

家里的那些个 70 后 60 后亲戚有种这样的风气,每次家庭聚会串门喜欢在茶余饭后用很恶毒的语言去谈论一些其他人的八卦私事流言蜚语,说话非常难听,满嘴脏话下三滥的低俗语言,靠挖别人的烦恼痛处用刻薄的语言来挽回起自己那可悲的满足感,并乐此不疲笑哈哈,我相信如果我和他倾诉的足够多,他们在别人那里一定也会这样讨论我。

14. 深入理解 android 包体积优化,给 apk 瘦身全部技巧

前言

随着 iphone13p 最大内存放大到了 1T ,大内存手机的时代悄然降临,在 android 里面,三星也有,罗老师几年前说:如果我告诉你们我们在做 1T 的手机,你们可能以为我疯了

看看现在,估计未来会有更多手机有 1T 版,大家开始真香了。

但是,如果现在有人说:要做一个 1T 大小的 app ,那他可能是真疯了,至少未来十年不可能。因为手机内存是越大越好,你一个 app 当然是能小就小呀

Android app 的文件格式为 apk ,本文就是探讨对于一个 android apk ,有哪些方法可以减小体积

Apk 组成

要想减小体积,首先我们需要了解 apk 的构成

373c7fa912fa93d601a2bee46c76ae2d.jpg

  • 我们写的.java 文件会被编译为.class 文件,再由 dx 工具编译为 Classes.dex 文件,由于 android 限制,每个 dex 文件最多 65535 个方法,所以多出来的方法就生成 Classes2.dex , Classes3.dex~ClassesN.dex

  • Resource(res)与 Assets 比较像,区别是 res 目录下会生成资源 ID ,并在.R 文件中记录,可以直接使用,这里平常我们用得很多,而 assets 不会有 ID ,而是通过 AssetManager 接口获取;

    所以 res 类似于我们的桌面,一般放我们要操纵的控件资源,而 assets 类似于桌下的抽屉,放诸如数据库,html 这类资源

  • Native Libraries 平时打交道少,优化空间也很有限

上面是抽象的 apk 结构,下面我们看一个实际的

将 qq.apk 拖入 android studio

image-20211023160756347

可以看到最大的 R 文件夹,点进去,都是一些图片,第二大的是 assets ,里面是一些表情包以及插件图片

其他的我们刚刚也说过,值得注意的是,里面多了一个 META-INF

他存放了应用的签名信息,其中

  • .MF: 每一个资源都有一个 SHA1 签名,存放在这里

  • .SF: 文件存放.MF 经过 base64 编码后的签名

  • .RSA: 对.SF 文件使用 SHA1 算法生成数字摘要(注意:.MF 中是对每一个资源进行 SHA1 ,这里是对文件),然后进行 RSA 加密,再用开发者私钥进行签名,安装时使用公钥解密

这样子,一个 app 安装在手机时,解密这一数字摘要,然后与内部的.MF 文件比对,如果相符,证明资源内容没有被修改

Dex 文件

在 APK 组成中我们可以看到,占用内存最大的是 res ,assets 与 classs.dex 文件,这也是我们的优化方向,接下来,我们看看如何优化 dex

首先我们看看 dex 的结构

undefined

更详细的版本在官网,这里如果对这些结构的作用有兴趣,可以看下图的详细版本

image-20211023162712238

ProGuadrd

dex 是代码编译而来,而对于代码文件,最重要的优化就是混淆了,将方法名,属性名等变为又短又无意义的名字,不仅能缩小体积还能避免反编译被人破解

在 IDE 中,我们可以看到 qq 里面的类都是小写字母,里面的变量和方法都按字母顺序排列了,从 a 开始

image-20211023163108352

除了修改变量名,ProGuadrd 还可以在功能等价的基础上重写代码,比如把多个函数调用写到一个函数里面去,更加增大了阅读理解难度(虽然初学者一般已经这样做了),以及打乱格式,增加空格等

主要步骤如下

  • 压缩( Shrink ): 检测和删除没有使用的类,字段,方法和特性。

  • 优化( Optimize ) : 分析和优化 Java 字节码。

  • 混淆( Obfuscate ): 使用简短的无意义的名称,对类,字段和方法进行重命名。

  • 预检( Preveirfy ): 用来对 Java class 进行预验证(预验证主要是针对 JME 开发来说的,Android 中没有预验证过程,默认是关闭)。

D8 与 R8 优化

这两平时接触不多,他们主要是在字节码处做优化的,开发时感知不强(感觉就是用来面试的)

D8 主要是在编译字节码时重排序,将占用空间变得更小,比如对于 greetingType 方法,正常编译后的结果是

[000584] Main.greetingType:(LGreeting;)Ljava/lang/String;
0000: sget-object v0, LMain$1;.$SwitchMap$Greeting:[I
0002: invoke-virtual {v2}, LGreeting;.ordinal:()I
0005: move-result v1
0006: aget v0, v0, v1
0008: packed-switch v0, 00000017  // 这里

如果使用 D8 优化,编译后的结果

[0005f0] Main.greetingType:(LGreeting;)Ljava/lang/String;
0000: sget-object v0, LMain$1;.$SwitchMap$Greeting:[I
0002: invoke-virtual {v1}, LGreeting;.ordinal:()I
0005: move-result v1
0006: aget v0, v0, v1
-0008: packed-switch v0, 00000017  //  这里
+0008: const/4 v1, #int 1
+0009: if-eq v0, v1, 0014
+000b: const/4 v1, #int 2
+000c: if-eq v0, v1, 0017

可以看到 0008 处后的几条指令有变化,多了几个 if ,对于不同的 case 做创建不同的变量,可以节省空间

R8 也类似,只是策略有些不一样

更详细的了解可以参考 D8 Optimizations

总之,他们的作用是就是,在不改变功能的情况下,重写部分 class 指令,减小空间占用,但是有可能会增加指令数量

Redex 优化

Redex 是 Facebook 推出的一个优化 Dex 文件的工具,和 D8R8 一样,也是对字节码的处理,有以下效果

  1. 内联函数,减少调用
  2. 删除无用代码
  3. 将只有一个实现类的接口或者父类用实现类代替
  4. 字符串混淆所见

……

不过这个我没用过,但是感觉 Proguard 与 D8R8 都多多少少能做到,可能是他在细节上用了更好的算法

但是不管多少框架,对 dex 文件的优化说来说去也就这些

移除多余的库与代码

最后是移除第三方库和冗余代码,属于业务逻辑上的原因

  • 多余的库

    对于自己的小项目,还好,对于多人参与的大型项目,很有可能对同一个功能,不同的人用了不同的轮子,手 Q 里面就有,比如要写单测,之前使用 Powermock ,后来用 JMock ,再后来改为 Mockk ,一个项目,三个单测框架

    由于不同的单测框架已经写了不少单测,短时间移除是不太可能的,但是可以慢慢转为同一种单测框架

  • 多余代码

    Android studio 会自己检测,没有用过的会置位灰色提醒,但是会漏掉很多,通过插件 Lint 可以检测,

资源清理

上面都是在代码层面减小 dex ,apk 的另一个空间占用大户,是资源,尤其是其中的图片,

图片,你可知道,多少 OOM 因你而起?多少 app 因你闪退?

图片压缩与更换格式

我们先看看图片为什么那么大

图片的显示,有 ARGB 4 个通道,其中默认的显示模式是 ARGB8888 ,ARGB8888 表示每个通道的颜色区间为[0,255],也就是两个 16 进制数表示,也就是 8bit -> 1 字节

所以 ARGB8888 模式下,一个像素 4 个通道下占用 4 字节,一张 1024*1024 的手机图片图片,就是 $$ 2^{10} * 2^{10} * 2^2 = 2^{22} = 4M $$ 一张图 4M ,太离谱了!

上面是打开后在运存的占用,我们可以修改颜色通道,不然 ARGB565 来减小单个像素所占用运存,不过有点跑题,本篇我们讲的是 app 的大小,也就是所占用手机的内存(我们约定 手机运存 = 电脑内存,手机内存 = 电脑硬盘)

内存与运存中的图片存在形式是不一样的,压缩方法也不一样,很多人容易弄混

回到内存,内存中,图片是以 png ,jpg 等格式存储

我之前开发的时候都是先将 png 图片,往 tinypng 网站中压缩一下再放入,所以可以压缩图片,一般能压个三分之一~三分之二。

也可以更换图片格式,比如 webp ,svg 可以更小,android studio 也提供了对应的支持,但是没有最好的格式,只是适用场景不同

几种格式的优缺点

这里多提一下 webp ,因为这是 google 推出的,大家在谷歌浏览器下载图片的时候,一般默认下载下来就是 webp 格式,所谓更小的内存占用,本质上是对图片进行了压缩,webp 的压缩算法是 VP8 视频编码,核心逻辑就是将图片分割成更小的子块,然后预测周围像素值,预测越准,周围的像素值就可以删去,再在图片打开时算出删掉的像素

图片网络化

在微信或者 qq 聊天中,对方发来一张图片,我们在聊天窗口往往先看到一张很模糊的缩略图,当点击时才会加载出高清图,

这个思路也可以用在 apk 中,很多入口较深的高清大图,或者需要经常更新的图片,也许用户根本不看,就没有必要内置在 apk 中,看时加载即可,如果需要提前占位置,可以用缩略图代替

至于哪些图网络化,需要根据业务与用户体验来权衡了

比如淘宝,在断网情况下打开时,只有 icon 内置了

image-20211023211648469

其他策略

无论是对 Dex 还是对资源进行优化,虽然安全有效,但是本质上是将原来有的东西变得更小,对 apk 的瘦身程度是有限的,还有一些”七伤拳“,优化率极高,但是对 apk 的影响也很大,需要谨慎使用。

插件化

所谓插件化,就是将 apk 中的非主要功能弄成独立的 apk ,原主 apk 称为宿主。

比如支付宝里面,就是搞支付的,那么他里面的什么口碑,基金,天猫一堆乱七八糟,同时功能独立的东西就非常适合做成插件,用户用到的时候再从网络加载进来,这样极大的减少了 apk 占用。

但是这里涉及到比较多的技术问题:

  1. 用户现在只有宿主 apk ,如何让宿主加载到插件 apk 里面的代码?
  2. android 四大组件都需要到 manifest 中注册,插件里面的组件显然不可能提前注册到宿主的 manifest 中(不然注册了,插件没加载进来,会找不到类),所以如何让系统认为下载下来的插件有注册?
  3. 宿主与插件资源能否正确互相引用?

一般来说,通过的是代理和反射来处理,腾讯有一个 shadow 框架可以大致实现”零反射“,

  • 复用独立安装 App 的源码
  • 零反射无 Hack 实现插件技术
  • 全动态插件框架
  • 宿主增量极小
  • Kotlin 实现

不过插件化技术不在今天的讨论范围,有兴趣可以研究下tencent-shadow

当使用了插件化后,项目基本是要重构了,相比起改改 Dex 和图片,这个工程量极大,但是收益也会很高

webview

这里类似于图片网络化,相对于图片,直接将整个界面都变成 url ,

我们手机 app 中的小程序一般都是 url 显示在 webview 中

相关技术可以使用 jsBridge 与 Hybird ,本质上就是通过 bridge 连接 h5 与 android iOS ,实现通信

image-20211023201811533

不过代价就是,加载速度慢于原生,还要注意防止网址篡改等

小结

本文我们讨论的是 apk 的瘦身方案,首先先明确了 apk 的主要组成部分为 dex 文件与资源文件

  • 对于 dex 文件,我们可以进行混淆,字节码重排序,移除多余库与代码

  • 对于资源文件,我们可以替换格式,压缩图片,网络化

除了这些常规操作,我们还可以使用插件化与 Webview 方法极致减少体积,但是这两个技术工程量大,而且有性能代价,需要谨慎使用。

参考资料

深入探索 Android 包体积优化(匠心制作-上)

Android 项目中资源文件 -- asset 目录和 res 目录

顶象 App 加固技术解析:DEX 文件格式的详解

D8 Optimizations

Android 开发应该掌握的 Proguard 技巧

15. 有趣的问题: iPhone 年年丐版 trade in 和顶配用三年的折旧?

年年 trade in 丐版的三年折旧是多少,顶配用三年的三年折旧是多少?

算起来可能比较麻烦,要搞清楚每一笔的概念,尤其是年年换的话每年的钱要单独算一遍折旧。

不过还是很有趣,我怀疑每年都换新手机和一部 1TB 存储的机器用三年的折旧率是差不多的。

16. 请教一个 WSL2 上代理的问题

因为 windows 分配给 wsl2 的 IP 是动态变化的,所以我在.bashrc 设置了如下环境变量,我想用curl cip.cc检测终端是不走代理,但返回的是国内当地的 ip 地址

export host_ip=$(cat /etc/resolv.conf |grep -oP '(?<=nameserver\ ).*')
export https_proxy="http://${host_ip}:7890"
export http_proxy="http://${host_ip}:7890"
export all_proxy="http://${host_ip}:7890"

所以请教下大家,终端走代理的正确姿势该怎么操作呢?

17. 请教一下,关于光猫,桥接, dmz, ap 的性能问题

结构 1:internet----光猫( PPPOE )---<dmz>---无线路由------PC

结构 2:internet----光猫---<桥接>---无线路由( PPPOE )------PC

结构 3:internet----光猫( PPPOE )---无线路由( AP 模式)------PC

现在家里的是 sdn 网关,要改桥接比较麻烦,得师傅上门。

所以想请问一下,结构 1 和结构 3,哪个性能会好一些呢?

光猫型号是 HG2821T-U,路由型号 XDR3250

另外,有什么比较好的测试整体路由性能的方法?

谢谢

18. M1 MacBook Pro 13 16GB 1TB 有必要 Trade in 升级 M1 Max Macbook 16 64GB 1TB 吗?

请问大家 M1 MacBook Pro 13 16GB 1TB 值得 Trade in 升级 M1 Max Macbook 16 64GB 1TB 吗? 目前使用方式是 13 寸的链接 xdr 显示器 用的时候盖上笔记本,(说真的好烦,喇叭全被挡住声音好闷)。 每日使用最多的是 Numbers Keynote ,稍微有时候 final cut pro 。 玩英雄联盟 但是带不动 XDR ,16 寸会不会好一点呢?

19. Macbook Pro 发货了
14 寸 Max 32 ,64GB ,2T 今天上午 10 点多发货了,预计到达时间 26 日。

20. 一个小白想法, Python 为什么不通过命令行开关切换两种 GIL 模式?
最近 python 出现一个惊艳的 no-gil 设计,想必大家已经知道了。

那么对于 python GIL 这个老问题,似乎常见的说法是:
粗粒度的 GIL 降低多线程的性能,细粒度的 GIL 降低单线程的性能。

那为什么不全都要,通过命令行开关切换两种 GIL 模式?
我本身并不太懂同步原语、线程安全、并行编程这些,所以想请教一下。欢迎指正!
21. 问问 20 款 MBP 值什么价,附近正好有人收
MacBook Pro 2020 13 寸 16+1TB 版本
- 2.0GHz 4 核 Intel Core i5
- Intel Iris Plus Graphics
- 无拆无修,98-99 新,无磕损无划痕
- 2020 年 8 月 12 购入
- 带 touchbar
- 电池循环 89 次