从财富帮项目启动到现在也半年多了,开发过程中零零散散地也积累了一些经验心得,今天把财富帮iOS客户端的一些设计思路跟大家分享一下,权当抛砖引玉。因为分享的是思路而不涉及具体实现细节,所以也同样适用于Android哦。
Debug页面
一个好的App除了实现正常的功能外,还应该有一个良好的debug机制。这个Debug机制应该用一个隐藏的不易被普通用户发现的方式去实现,值得庆幸的是iOS和Android系统都提供了Url Scheme技术,用来从外界打开App的一个具体页面。
财富帮目前的Debug页面对一些不易在运行时调试的功能添加了辅助功能,比如推送。对于推送,我们设定了推送日志,用来收集服务器推送过来的信息。分析这些消息可以帮助我们精准的分析出问题到底出自服务器端还是客户端甚至问题的具体原因。另外,对于推送我们还设定了账号绑定机制,这个绑定于设备的账号主要被用来做单推测试。单推测试是推送测试中很重要的一个环节,一般情况下只要单推测试过了,群推就是n个单推而已。除此之外,财富帮Debug页面还设置了切换App运行环境的功能,把这个功能放到Debug页面是因为这是一个敏感操作,一般用户不应该拥有这个权限,甚至不应该知道这个功能。这个功能主要是为了方便开发人员和测试人员用一个安装包去切换环境以测试App在不同环境下的表现,免去了开发人员针对不同的环境要打不同安装包的琐碎工作。
客户端多环境切换
在实现这个功能之前,我们首先要思考一个问题,测试环境、正式环境以及开发环境和预发布环境等真正的区别在哪里?仔细想想后不难发现,UI交互、业务流程等几乎是一模一样的,唯一不同的就是请求接口的Url,和某些第三方的App key,App id等,比如说推送的App Key,微信分享的App id之类的。
为了实现环境切换功能,我们首先要实现一个管理请求Url的类,我们可以暂时把这个类叫做CFBRequestUrlManager,它主要负责根据不同的环境返回不同的请求url。然而,我们到底该如何标记环境呢?很简单,客户端本地存储一个变量app_env就可以。现在数据层就基本ok了,我们还需要在Debug页面加上一个分段控件用来让用户操作,记得在分段控件切换环境时更新下app_env就可以。现在关键的问题来了,切换环境后除了更新app_env,我们还需要做其它事情么?当然需要了,想想推送,推送环境的初始化注册等操作都是在App启动时做的,再想想App里某些模块的缓存,如果不清除掉的话,我们切换到了新环境却还在用着上一个环境的缓存,这会引起多大的bug哇;这里只是举个例子,真实情况下应该还有很多具体的问题。简言之,我们需要在App切换环境之后做好清除缓存等工作。最后也是最重要的,为了让推送等需要在App启动时才能执行的逻辑实时触发,我们应该退出App。
推送debug
1.推送日志的建立
推送的使用场景往往是在App发布之后,这个时候我们的App需要根据服务器推送过来的信息来决定App展示什么样的页面,执行什么样的逻辑;此时,我们是无法用IDE来Debug的。倘若能针对具体的业务逻辑建立一套自己的推送日志,那么我们调试推送功能时将事半功倍。财富帮目前的推送有好几类,以资讯推送来做个简单例子,对于资讯推送我们很关心推送过来的点击url,以及是否允许分享,分享url等,我们把这些信息都写入日志的话,假如某条资讯推送过来出现了打开为空白页面,或者不允许的分享的却显示了分享按钮等bug时,我们就能很容易地定位到错误,然后迎刃而解之。
2.别名账号的建立
有的推送功能提供商在测试单推功能时是不允许使用deviceToken的,它们需要一个设备别名,财富帮现在所使用的信鸽推送就是这样。为了测试单推功能,我们在Debug页面设定了一个绑定推送别名的功能以方便测试单推功能,必须要提醒的是,设备别名的绑定时机是在App 启动的时候,所以当我们绑定了新的设备别名之后,必须先重启App才可以重新测试。
托管式网络请求类
在移动客户端的开发过程中,我们需要经常处理网络请求,关于一个网络请求我们大概有三个关注的时间点,请求开始,请求成功或失败。对于大部分请求,我们都需要做同一件事情,请求开始时显示loading动画,成功或失败后移除loading动画,失败后根据失败原因显示不同的UI,如果是因为超时原因,页面应该提供一个非常重要的刷新按钮,点击之后能重新请求数据;如果是网络情况不好或服务器内部错误,则应该根据错误原因显示相应的提示页面,此时不需要提供刷新按钮。
由于在一个App内,loading视图,网络超时视图,以及服务器错误视图基本上都是统一风格的,所以对于这三个视图的具体表现,我们完全可以提供抽象接口去实现。我们可以根据一个网络请求对象是否实现了相关接口来决定这个网络请求对象是否需要托管,如果实现了则为托管状态,执行相应的托管逻辑,也就是请求开始显示loading视图,请求失败显示相应的错误提示页面。这种情况一般适合于一个页面的主网络请求,所谓主网络请求就是请求下来的数据能够渲染这个页面的大部分区块的UI。对于一些小的附带请求,只影响局部UI的请求,我们不应该实现托管,以免影响页面整体的视觉表现。这样我们就初步实现了托管式网络请求类,但是如果每个请求我们都需要实现一次接口那不是很累么?!
所以刚才设计的网络请求类应该只能是一个基类。一般情况下,一个App里的网络请求loading图,网络请求超时图应该是相同的,为了贯彻DRY原则,我们还需要设计一个子类继承刚才的基类,这个子类应该实现相应的loading视图,网络超时视图逻辑接口。最后,为了让基类更健壮灵活,我们还需要提供一个BOOL标记来决定是否启用托管,如果启用,则执行loading,网络视图等逻辑,反之,则不执行。
网友评论