Flutter 学习资料及笔记总结

也许是程序员天生的鄙视链作祟,后端出身的自己一直认为前端/客户端就是一个“画皮”的事,因此一直不愿意投资时间系统地学习前端技术栈。一般都是实在不得不做前端的时候,在 github 找个功能需求差不多的代码库,修改一下上线。开发速度倒是很快,但是出来的效果总是被评价为“程序员审美”。

一直在寻找一个性价比高的方案,希望能够真正 Write once, run anywhere. 对于桌面客户端,尝试过一段时间 Electron, 但是发布安装包的体积大以及web级别的性能使得只能在有限场景下使用。移动端,当前最火的自然是 RN. 但个人是在受不了RN中屁大点的事情都搞得复杂难用,因此一直也是敬而远之。而去年12月Google发布的Flutter却让自己有了眼前一亮的感觉。

RN vs Flutter

Flutter比RN晚出生两年,而在很多概念上,其实也是借鉴的RN。无论是从社区还是成熟度来看,Flutter都还有很长一段时间要走:

但是,Flutter的设计哲学更加简单,更符合自己的品味。举个例子,Flutter中,几乎所有的UI元素都是一个 widget, 没有那些乱七八糟故弄玄虚的概念,一切都非常直白。从上表的比较可以看出,其实技术层面,Flutter其实并没有绝对的优势,在社区和成熟度上还有明显的短板,但这些都不重要。重要的是,判断一个技术是值得投资,要看未来三五年中,这个技术有没有可能成为行业标准,尤其是在大公司引领下成为事实标准。

显然,Flutter具有这样的潜力。移动开发中,在 web/H5 无法覆盖的场景,在效率和成本的驱动下,跨平台开发会是行业的趋势。最近火热的 996.icu 也算是一种从侧面透露出以后并不需要那么多的客户端开发同学。另一方面,Flutter 是Google为下一代操作系统Fusion的重要布局,且有chromium项目加持。无论从战略还是项目层面,都是天空给的足够高,翅膀长的足够硬。从这个层面看,RN简直就是一群小学生在玩过家家了(开个玩笑,不要当真)。国内方面,无论是阿里还是腾讯,都开始在Flutter上进行布局和项目技术投入。需要特别指出的是,在Flutter之前,阿里是有自研 Weex的,具体项目上,闲鱼团队已经有在实际项目中使用 Flutter.

Flutter 学习资料及笔记

Flutter 可以简单的理解为一个使用Dart语言进行开发的跨平台UI框架。因此,入门需要学习的东西主要有两块:

  1. Dart语言;
  2. Flutter 框架;

Dart 语言设计之初是为了替代 Javascript, 因此,整体上没有那么多语言bug, 会比 JS 要更加符合后端同学的语言习惯。语言入门只推荐一个官方的 A Tour of the Dart Language 学习资料。看资料的过程中,可以结合 DartPad
写一些代码片段,辅助记忆和理解。Dart 语言学习笔记:

  • 一切皆对象,默认值都是null
  • 下划线开头的变量是私有变量,跟Golang的语言设计风格类似
  • 基础类型转换,依赖 parse 和 toString 方法
  • string是 utf-16, 有点非主流
  • 函数默认值必须是 const, 规避不可重入的问题
  • Dart的所有异常都是 unchecked exception,且可以抛出任意object作为异常
  • 构造函数可以取名称,便于阅读理解,但是这点改进对于引入的复杂度并不划算

整体看,Dart 引入的一些语言特性是 python + Java 的合体。语言上中规中矩,没有什么亮点。可以看成是 javascript 的静态类型版。但是,谁让Dart搭上了Flutter这趟潜力股,而Flutter又找了Google这个大干爹呢。老实学吧,反正也就一两个小时的事。

关于Flutter本身的学习资料,其官方网站的文档一如既往地保持了 Google 级文档的水准。但是官方文档有点大而全,可能没有足够时间通读,一时半会也不容易抓住重点。我推荐几个资料你一定要仔细阅读:

学习完以上资料,附带一些课程联系,你会花大约1~2个周末的时间。学完以后,你已经初步具备开发跨平台 app 的能力了。(我个人的情况是, 两个周末学习完上面的资料,并完成一个简单的 app 开发并提交到app store审核,相信你也能做到。)

在开发app过程中,你可能会查找组件,这里推荐阿里的flutter-go.

如果需要进一步深入,可以阅读学习其他人的代码

此外,如果你关注 Flutter 在桌面端的跨平台情况,由于官方还没有发布桌面支持的正式版本。推荐你当前先watch Desktop Embedding for Fluttergo-flutter 两个项目。

总结

在Google Fusion战略和明星项目chromium加持下,以及国内巨头积极跟入的背景下,花两个周末系统学习一下Flutter个人认为是一个潜在投资性价比很高的事情。另一方面,Flutter从去年12月才发布1.0正式版,整体成熟度还不是很高,因此在实际项目中并不建议太激进的引入使用,并且Flutter在一些原生支持上海不够完善。比如,使用Flutter接收其他app分享的内容,android平台下你可以根据How do I handle incoming intents from external applications in Flutter?来解决,但是在iOS平台,当前阶段则是彻底不支持。

四五年前iOS客户端开发炙手可热的机会已经一去不复返了,Flutter也许是下一个机会。

获取 Instagram 用户所有图片手记

我是一个 Instagram 重度用户,关注了很多有意思的 po 主,因此经常需要将这些 po 主的所有图片打包下载。(国外非常注重版权,下载图片只能个人使用,商业用途请严格遵循版权保护流程。)

ig 的账户分为公开账户和私有账户。这里只讨论公开账户的图片的获取方式。

我们知道在 ig 用户的 profile 业务可以看到用户发布的所有图片,例如:https://www.instagram.com/instagram/,即格式为:

很久以前,我们通过 https://www.instagram.com/{username}/?__a=1 的方式可以获取该用户的所有图片。但是这个方法被大家玩烂了,ig做了一些限制,先是下线了这个私有接口,后来又恢复了这个接口,但是需要用户处于登录状态。考虑到这个接口被下线过,继续使用该接口不确定性较大,且让帐户处于登录状态去调用这种私有接口被封号的概率是很大的。于是,尝试使用其他方式。

前端无秘密,ig 的接口其实还是比较奔放的。在用户 profile 页面转了一圈,发现其使用了一个通用的 graphql 接口来获取用户图片:

那么接下来的事情简单了,确定其请求的参数就可以模型请求获取用户图片了。

query_hash 参数

query_hash 在接口中的作用类似于让服务器知道客户端的版本,这个参数被 hard-coding 在前端的一个 js 文件中。在我的网络环境下,该 js 文件是 b55cb2cfaa46.js,值为 f2405b236d85e8296cf30347c9f08c2a.

该参数获取非常容易,唯一不太确定的是其更新的频率。从实际使用情况来看,这个值已经一个多月没有更新过了。因此,一周自动检测更新一次应该是没有问题的。

query 参数中的 variables 都是业务参数,看一眼就明白。但是,实际测试你会发现,所有的query参数都正确的情况下,服务器依然会返回 403. 二分排除了一下,发现是 header 中的 x-instagram-gis 是一个请求签名验证参数。只有该参数通过了验证,才能获得预期的返回。

x-instagram-gis 参数

签名的生成算法是:signature = md5({rhxGis}:{queryVariables}). 对应 js 实现:

rhxGis 参数可以通过用户页面的全局变量 window._sharedData 获取到:

queryVariables 对应上诉 variables 参数。

至此,关键参数获取方式都已搞定。可以开心的在 ig 上逛图啦。

扩展阅读

How to perform unauthenticated Instagram web scraping in response to recent private API changes?

2018 年终总结

2018 年终总结

年末被各种事情推着走,总结拖到现在才写,也算是保持了过去一年平均时间管理水平?。

过去的一年,发生和经历的事情挺多,也逐渐到了很多事情不太适合写出来尴尬年龄。不过,一直在路上,缺少盘点的话,总觉得对自己缺乏那么一点交代。

过去的一年,重新捡回来写作的习惯,同时也开始鼓动身边的人开始写作。毕竟这是当前仅存的几项只有好处,但咸有坏处的活动。过去的一年,每月至少有一篇输出,同时靠写作赚了几杯咖啡钱,也因为写作,连接到了一些素未谋面的有趣灵魂们。其中,收到过一位自己喜欢的“大佬”的打赏。这是一些好的方面。换工作以后,写作的时间和频率被动减少了很多,借口就不提了。但好不容易养成的习惯,是无论如何不能被摧毁的,新的一年希望自己有更多与自己交谈的思考和沉淀。

过去的一年,离开了自己舒适区,换了份工作。其实非常舍不得前东家,我知道作为在职场混迹多年的人,依然说这种话是非常不成熟和忌讳的。但是,离开真的并不是因为它有什么不好,只是因为未来两年,我有自己想成长的方向和天空。开弓没有回头箭,下山的弟子要去爬属于自己的那座山,没来得及好好道别的兄弟们,我们江湖再见。来到新的工作岗位心态非常平和,这也是自己一直以来希望自己面对任何事情的基本心态——在智力、心里、脑力、体力之外,一定不能扭曲的就是心态。新的位置压力不大肯定是骗人的,但是希望自己能够保持好这份心态。要不了几年,我依然会从这个山头下山,人说雁过留痕,我希望自己能对得起自己当年的那次下山,当然还有自己的年轮。

过去一年,没有什么像样的出游,如果一定要记录一下的话,那就是在青城山下悠闲的几日,以及带家人去了一趟乐山。这种出游距离和时间,对于成都人来说,也就是一个周末亲自游的水平。但是青城山下,因为放下了所有事情,逛着经不起历史推敲的道观,也算是难得的放空。乐山之行算是特意为家里的四个女人安排的:婆婆,老妈,妞儿还有女儿。乐山我跟老爸都去过很多次了,但是对于前面四位在某些层面来说都是新的:婆婆、女儿从来没有去过乐山;老妈去过乐山,但是没看过大佛;妞儿去过大佛,但是因为四年前自己安排不当,并没有尝到乐山的美食。一天的逛吃下来,在力所能及范围内,用尽了一切便利条件,大小老少都累得够呛。晚饭时候,婆婆说”今天最幸福“,我知道他们那一辈人是很难表达这些感情的,能说出这句话,我真的觉得自己歪打正着的这次安排真的太幸运了。

过去的一年,纸质阅读时间和质量都下降严重。有时候,我甚至已经开始怀疑自己被算法推荐的狗粮给喂成了?。这是过去一年时间管理出问题的一个侧面,每天警醒自己,但是每天依然岿然不动,也算是极致的讽刺了。新的一年,需要改变。

过去的一年,莫名其妙的看了很多场电影。最推荐的是《我不是药神》,影评层面的就不提了,仅仅是因为这是这几年陪老妈看的第一部电影。希望以后能陪父母看更多的电影。

过去的一年,经济很冷。自己在投资层面稍有盈余,看看身边各种腰斩的兄dei,至少不算太差。被动收入方面,完成了几个流程性的事情,虽然远比自己预想的要慢,但是这个事情本来也就是在认定的方向上去祈求一个时间的礼物,急不得太多,但须一直坚持下去。希望来年,能有一个姑且能称为产品的达到自己设定的目标吧。

过去的一年,依然没有学会如何哄女儿。跟别人说起来头头是道的 positive 式引导教育,自己实践起来屁用没有。我现在已经接受女儿当前 double two 阶段的这种超乎常人的顽皮,也许她在 third two 的时候,这种顽皮会有所收敛?天知道呢。

过去的一年,送给了妞儿一个大件礼物。其实,她至今没有正式的跟我说声谢谢,但是我能感受到事物本身对她认知的影响。有些事情,不仅是责任,更是义务,其他的并不重要。

过去的一年,没有买到自己心仪已久的大房子,挺遗憾的。希望来年准备好更多子弹,给家人一个更好的居所,也给自己一个更舒适的奋斗窝。

2018年初,我知道会发生很多事情,但是真正做一些事情让预想发生的时候,自己早已没有当时的兴奋,反而会带来一些自己没有考虑到的问题。你说这些重要吗?肯定重要,因为它会影响你的轨迹;但是也没那么重要,毕竟我过去做过如此多最坏的选择,其实也没有太糟糕。新的起点,我想在自己认真的事情上保持认真和专注,在自己没有那么认真的事情上,想清楚,要么认真起来,要么随他而去。2019,心之所向,不过如此。