Edison Wang
Twitter/Vine资深安卓工程师
构建并启动一个应用,既有趣又简单,但接下去就要维护;您不断地增添特性、事件和业务逻辑。 您的团队里增添了新成员,现在要跟踪发生了什么就不太容易了。您需要一种好方法来有条不紊地整理代码。 测试是起步的好方法。 您不断向有限状态机中增添状态,但最终发现无法再跟踪,于是您增添 Otto、EventBus、Dagger、Rx 和其他框架, 但是,在进行代码重构时,为确保调试过程有条不紊,要在编写太多样本文件代码:界面之间找到一个最佳状态却如此困难。
于是 Penn Station应运而生,这是一种利用 EventBus的安卓服务型式:受 iOS 的 Grand Central 启发,将您的应用中的事件设想为人们,他们试图从这里前往那里(请求器/侦听器),因此他们聚集在 Penn Station,在这里,他们可以前往 NJT/LIRR/NYC Metro/etc(不同的进程)。(Penn Station 是纽约一个地铁站,NJT/LIRR/NYC Metro 是新泽西/长岛/纽约市——译者注)
Penn Station | EventBus | Otto | |
---|---|---|---|
声明事件 | 标注 | 标注 | 标注 |
事件侦听器接口(2) | 标注 | 否 | 否 |
事件请求工厂 | 标注 | 否 | 否 |
事件结果工厂 | 标注 | 否 | 否 |
IPC 经由 Parcelable(如需要) | 是 | 否 | 否 |
事件生产器 | 标注 | 否 | 是 |
请求实施 | 是 | 否 | 否 |
异步交付 | 是 | 是 | 否 |
在张贴线程上的事件交付 | 是 | 默认 | 否 |
在主线程上的事件交付 | 默认 | 是 | 否 |
在背景线程上的事件交付 | 是 | 是 | 否 |
请求进程 | 服务执行器 | 背景 | 背景 |
方便访问语境 | 安卓服务 | 否 | 否 |
使用 Penn Station,您实施长时间运行任务的流程就十分方便,因为除了考虑需完成什么任务、何时完成该任务、应发出什么事件外,您不必担心其他任何事情。
设想您在编写一种登录用户的方法:
首先,创建一个实施 BaseAction 的 LoginAction:
- 通过 @RequestFactory 标注该 class
- 通过 @RequestFactoryWithVariables 标注该 class a. @ClassField(“username”, String.class) b. @ClassField(“password”, String.class)
- 通过 @EventProducer 标注该 class a. @ResultClassWithVariables(“Failed”) b. @ResultClassWithVariables(“Success”)
- 在 processRequest 内部实施该逻辑。
- 通过返回 Failed 事件实施 onError。
现在就可在任何地方使用此 LoginAction,只需声明需要 LoginAction 的任何 class 为 LoginAction.class 的 @EventListener:
- 实施 onEventMainThread(LoginActionEventFailed)
- 实施 onEventMainThread(LoginActionEventSuccess)
- 每当需要时,通过生成的 PsLoginActionAction 调用该动作。
这很好,因为:
- 封包:LoginAction 容纳所有逻辑和声明。
- 状态解耦: a. 不必担心生命周期:LoginAction 的生存随 Service,而非 Activity。 b. Listeners 有其自己的生命周期,如果其结束,那就结束了。
- 编译器辅助的代码重构: a. 如果您新增一个 result 类型,例如 “Expired”,在实施 “LoginActionEventExpired” 之前,所有 listeners 均不编译。 b. 如果要更改 request(请求),例如,增添一个 “birthday” 字段作为登录的必要参数,只需增添一次,然后每处调用 LoginAction 的地方都将要求输入该变量。
我希望,有了这个库,任何人可以编写改善用户体验的有效率、可伸缩和安全可靠的代码。
如果您有任何意见或建议,请不吝指教! :)