一、三种常见的状态管理
- Widget 管理自己的状态。
- Widget 管理子 Widget 状态。
- 混合管理(父 Widget 和子 Widget 都管理状态)。
1.1 Widget 管理自己的状态
1.1.1 适用场景
如果状态是有关界面外观效果的,例如颜色、动画,那么状态最好由 Widget 本身来管理。
1.1.2 例子
1 | class TapboxA extends StatefulWidget { |
如果状态是有关界面外观效果的,例如颜色、动画,那么状态最好由 Widget 本身来管理。
1 | class TapboxA extends StatefulWidget { |
canUpdate(...)是一个静态方法,它主要用于在 widget 树重新build时复用旧的 widget。
Element对象的配置。newWidget与oldWidget的runtimeType和key同时相等时就会用new widget去更新Element对象的配置,否则就会创建新的Element。Element 类。RenderObject 类。Layer 类。Render 树中。Element 是 Widget 和 RenderObject 的粘合剂。1 | Container( // 一个容器 widget |
笔者在《WKWebView》一文中提到过,WKWebView 在独立于 app 进程之外的进程中执行网络请求,请求数据不经过主进程,因此,在 WKWebView 上直接使用 NSURLProtocol 无法拦截请求。所以如果需要使用到拦截请求,有种可行地方案是使用苹果开源的 Webkit2 源码暴露的私有API(详见原文第3小节:NSURLProtocol问题)。
但使用私有API,必然带来以下几个问题:
由此看来,在 iOS11 WKURLSchemeHandler [探究] 到来之前,私有API并不那么完美。
所幸通过寻找发现,iOS系统上具备搭建服务器能力,理论上对实现 WKWebView 离线资源加载 存在可能性。
基于iOS的local web server,目前大致有以下几种较为完善的框架:
因为目前大部分APP已经支持ATS,且国内大部分项目代码仍采用OC实现,故本文将以 CocoaHttpSever 为基础进行实验。
Telegraph 是为补充 CocoaHttpSever 及 GCDWebServer 不足而诞生,对于纯Swift项目,推荐使用 Telegraph 。
在iPhone 6s、iOS 10.3.2中,对 http://www.qq.com 进行10次请求,得到如下数据:
| 次数 | UIWebView 内存消耗 | WKWebView 内存(APP)消耗 | UIWebView 请求耗时 | WKWebView 请求耗时 |
|---|---|---|---|---|
| 1 | 67.47 MB | 0.81 MB | 4.13 s | 0.80 s |
| 2 | 58.23 MB | 0.86 MB | 1.16 s | 0.54 s |
| 3 | 57.83 MB | 0.50 MB | 1.14 s | 0.56 s |
| 4 | 59.38 MB | 0.88 MB | 1.08 s | 1.07 s |
| 5 | 59.70 MB | 0.75 MB | 1.07 s | 0.71 s |
| 6 | 64.05 MB | 0.83 MB | 1.47 s | 0.65 s |
| 7 | 59.45 MB | 0.81 MB | 1.11 s | 0.63 s |
| 8 | 57.55 MB | 0.45 MB | 1.15 s | 0.64 s |
| 9 | 58.47 MB | 0.77 MB | 1.17s | 0.75 s |
| 10 | 58.89 MB | 0.84 MB | 1.11 s | 0.70 s |
UIWebView平均内存消耗:54.13 MB
WKWebView平均(APP)内存消耗:0.75 MB
UIWebView平均请求耗时:1.46 s
WKWebView平均请求耗时:0.7 s
综上可得:WKWebView在请求耗时上为UIWebView的50%左右,内存上更是完胜。但实际上 WKWebView是一个多进程组件,网络请求以及UI渲染在其它进程中执行。仔细观察会发现:加载时,App进程内存消耗虽非常小甚至反而大幅下降,但Other Process的内存占用会增加。所以:在UIWebView上当内存占用太大的时候,App Process会crash;而在WKWebView上当总体的内存占用比较大的时候,WebContent Process会crash,从而出现白屏现象。