开发一款App,就犹如写一篇命名文章或设计一栋楼房。在你动笔之时,文章已然成竹于胸;在你搬起第一块砖,楼房的概貌已经定型。故在你敲下第一行代码之前,务必要仔细想好App的架构才行。
我们知道,App中数据无外乎存在于这几个地方:内存、手机磁盘与网络上。编程其实就是对这些数据的迁移,上传或下载,再搭配友好的界面呈现给受众。你发一条朋友圈,数据由手机上传至服务器,然后你的好友再将其刷新下载至它自己的手机,完成阅读~
那么,作为一名程序猿(媛),你会如何设计用户按下“发送”按钮之后的数据迁移与界面更新之路呢?
方法一:
方法一View
通知ViewController
,“快把这条动态分享到朋友圈~”,为了界面友好性,然后ViewController
显示一个对话框让用户进行等待,此时ViewController
将这条动态交付给Network
,开始三次握手,建立连接,写数据,读取响应结果最后关闭连接,完成数据发送。Network
将发送成功结果告知ViewController
,“已顺利发送到朋友圈,不谢”,ViewController
隐藏等待对话框,并通知View
去绘制这条动态。
发送路线:View->ViewController->Network
回调路线:Network->ViewController->View
一切逻辑看起来都是那么的正常,当然这是以程序员的眼光。而在手机前盯着屏幕的网友们可能就无法忍受界面弹出对话框不停旋转等待发送的设计了,他们愤怒的评论会铺天盖地。
于是,方法二:
方法二你尝试着在ViewController
与Network
中,引入了Model
层,并打算去掉烦人的loading对话框。
数据沿着View->ViewController->Model
迁移,而后Model层同时做两件事情:
-
Model->ViewController->View
立刻回调ViewController
,通知刷新界面 -
Model->Network
开始将数据发送至网络
此时动态已经显示在了界面上。在由Network
完成发送之后,数据再一次的沿着路线Network->Model->ViewController->View
通知确实是完成发送了。
看起来比上次好很多了。但是当用户重新打开手机之后,有明显的延迟感来显示刚才发送的动态。哪里有问题?
问题就在于Model
层。启动App
之后,View
向ViewController
查询数据,ViewController
从Model
层拿数据,而此时Model
层还没有数据,因此又得通过Network
拿数据进行等待,因此便有了数据延迟显示的问题。
方法三:
方法三Model
换成了Persistent Model
,并引入了Application Logic
组件。
Application Logic
组件用于两个用途:
- 与
Network
进行数据同步 - 将数据更新至
Persistent Model
即业务逻辑迁移至了Application Logic
组件中,它扮演的是数据路线的调度器与通知器。系统各个组件都做着自己分内的事情,解耦合,易测试。
发送数据:View->ViewController->Application Logic->Persistent Model
当写入Persistent Model
成功,进行Callbac
通知View
绘制:
Persistent Model->ViewController->View
与此同时:Application Logic->Network
当发送至Network
成功,进行Callback
通知View
绘制
Network->Application Logic->Persistent Model->ViewController->View
这一切看起来是那么的完美。Run~~~生活总在你洋洋得意的时候,给你一记重拳…连续发送好几次之后,有时候按下了发送,界面却迟迟没有及时刷新,What's wrong?
原来,我们的任务线程现在已经too busy不堪重负了。解析图片,写入数据到磁盘,进行Http数据上传,又要写入数据,又有新的Http数据上传,在网络状况特别脆弱的情况下,可能因为一次Http长时间的调用,后面所有的操作就都全得wait啊!
后台队列方法四:
最终…你讲这一个有一个的任务进行划分,分别引入至两个不同的任务队列中,互不影响。此处应当有掌声。
双队列估计有的同学其实已经知道了,这其实是2015年Android开发者峰会上Yigit Boyar和Adam Powell通过一款小软件“Puppy Love”向大家讲解的知识点:用户体验的设计 (Architect for UX)。总结下来如下:
Design for offline (离线设计):
- UI的数据从Model层获得
- Application Logic 负责同步Model和Server
- 二者互不干涉
而关于Application Logic类的设计:
- 如果有可能,请使用依赖注入
- 考虑使用它的副作用
- 避免因为它影响性能
关于Network的设计与建议:
- 你的后台就是为你的App而设计的
- 在服务器端做尽可能多的事情
- 给客户端传递
Metadata
信息 - 尽可能的一次请求多条数据
什么叫做Metadata
信息,就是当你想要获取图片的时候,你不止拥有图片url这一个资源
但是在这个图片完全下载成功之前,你要想显示图片就比较棘手了,因为你不知道它的宽度和高度,创建placeHolder都比较棘手,所以提供我们需要更多的围绕着这个图片的metadata
信息:
现在知道了图片的宽度和高度,对于用户界面体验是不是有很大的帮助呢?
在实际开发中,除了Network
,Persistent Model
,还应该引入Memory
层,进一步尽速数据的展示与界面更新。这样数据迁移路线就变成了
View->ViewController->Memory->Persistent Model->Network
而数据同步路线也变成了
Network->Persistent Model->Memory->ViewController->View
这样在App内,数据同步逻辑按照此方式既简单正确,而又清晰易懂,是不是的确是一种优雅的方法呢~
欢迎大家关注我的微信公众号:coodelife,代码人生~
coodelife
网友评论