零、概述
架构/框架问题主要用于考察中高级、资深工程师。
1、为什么要在APP中引入框架?他有什么好处呢?
1)、模块化
2)、分层
3)、解耦
4)、降低代码重合度
一、图片缓存
1、怎么设计一个图片缓存框架?
2、图片通过什么样的方式进行读写,过程是怎样的?
以图片URL的单向Hash值作为key进行存储。读取流程其实就是浏览器的缓存读取流程,如下:
3、内存的设计上需要考虑哪些问题?
1)、存储的size
2)、淘汰策略
有两种策略:以队列先进先出的方式淘汰、LRU算法(即最近最久未使用算法)。
淘汰的时机有两种:定时检查(非常low,非常损耗性能)、提高检查触发频率(每次进行读写时检查、前后台切换时检查,这两种检查相对性能比较好)。
4、磁盘的设计上需要考虑哪些问题?
1)、存储的size
2)、淘汰策略
3)、存储方式
5、网络部分的设计上需要考虑哪些问题?
1)、图片请求最大并发量
2)、请求超时策略
3)、请求优先级:用户当前紧急使用的优先级高一些。
6、对于不同格式的图片,解码采用什么方式来做?
应用策略模式对不同的格式进行解码
7、在哪个阶段做图片解码处理?
在磁盘读取后和网络请求返回后进行解码处理,因为将图片解码后放到内存中可以减少显示时CPU的压力。
8、图片缓存框架时序图
二、阅读时长统计
1、怎样设计一个时长统计框架?
2、为何要有不同类型的记录器,你的考虑是什么?
基于不同分类场景提供提供关于记录的封装、适配。
3、记录的数据会由于某种原因丢失,如何降低丢失呢?
1)、定时写磁盘
2)、限定内存缓存条数(如10条),超过该条数就写磁盘
4、上传器关于延时上传的具体场景有哪些?
实时上传太消耗性能,所以需要使用延时上传,常用场景如下:
1)、前后台切换
2)、从无网到有网的变化
3)、通过轻量接口捎带。这条不符合企业级实现。
三、复杂页面架构(一般的页面MVC就够了)
1、怎样的页面算复杂页面呢?
比如微博APP的正文页、去哪网航班列表页今日头条等资讯类APP的多签首页。
2、复杂页面设计要考察的内容
1)、整体架构
视图层View中的操作:控件初始化、设置数据、交互事件通过代理控制
视图层VC中的操作:视图创建、组合;逻辑协调;View事件代理/回调的处理。
业务逻辑层ViewModel操作:业务逻辑处理,如将数据预排版;封装数据的增删改查(只是封装,并不是增删改查的实现);线程安全处理。
数据层Engine操作:网络请求、数据解析、增删改查(我认为一般用不到,只有向数据库存储时涉及)、本地逻辑处理(如Sever数据的适配)。
我的理解:大公司的话人员多要求质量,会用到Engine,小公司一般没有,一般图中Engine的层级都已经是网络层了。分层带来代码结构清晰易于维护,但是增加复杂度和成本,所以有些小公司连ViewModel层都不实现,直接都在VC中实现。
2)、数据流
网络数据我理解的就是网络传输过来的数据,一般为json;业务数据一般是json转化出来的model;UI数据比较复杂,是一个对象,对象包括frame和value两个属性。
3)、反向更新
很简单,就是页面初始的网络刷新、用户交互行为去通过VC->ViewModel->Engine加载数据,数据加载完后刷新页面。
作者所讲的反向更新是先给ViewModel数据打脏标记,数据更新回来后由ViewModel去遍历脏标记更新。用到了系统UIView更新机打脏标记思想和ReactNative的数据流思想。但是我觉得这样太繁琐,还是我的好。
3、复杂页面架构用到的思想
1)、MVVM框架思想
2)、ReactNative的数据流思想
子节点没有决定自己更新的权利,必须交给根节点遍历决定(根据各节点是否有脏标记遍历节点是否需要更细),即数据流是单向的。
3)、系统UIView更新机制思想==我不觉得反向更新用到视图更新时打脏标记的思想
4)、FaceBook的开源框架AsyncDisplayKit关于预排版的设计思想
四、客户端整体架构
1、客户端的整体架构是怎样的?
中间层:起到协调和解耦上层业务层各个业务的作用。
通用业务层(即当下App通用的组件,该App的各个业务线都需要用,但是另一个App不一定能用):自定义的步进控件、UIImageView的封装。
独立于App的通用层(即各个App通用功能):时长统计、日志统计、网络请求封装。
架构如上设计的话比较有弹性,很容易把某个/某些业务单拎出来称为新的App。
2、业务层各业务之间如何解耦?
1)、OpenURL
2)、依赖注入
需求:业务A需要调用业务C的某个功能。
解决:业务C注入中间层(中间层存储各业务遵守的业务代理协议,业务C启动时将自身注册为中间层的代理,其他业务需求业务C时通过中间层调用代理实现的方法),然后业务A去中间层获取它所依赖的数据。