移动开发 - Router组件
2017-09-01 本文已影响77人
豆志昂扬
MVVM+Router
在移动开发中讨论到Router的时候,一般直接想到的样式是这样子:
//iOS
//注册
Router.map("myapp://user/<int:id>", UserViewController.self)
//调用
Router.push("myapp://user/123")
Router.present("myapp://post/54321", wrap: true)
//Android
//注册
@Router("user/:userId")
public class UserActivity extends Activity {
...
}
//调用
ARouter.getInstance().build("/user/9527")
.withInt("age", 23)
.navigation();
引入Router后,页面/组件之间的跳转依赖于路由,可以降低其之间的耦合度。且、若应用支持推送或外部链接的时候,Router还可以让跳转到指定页面逻辑的逻辑复用,降低维护成本。
细心的读者会发现,上述Router只是解决了如何跳转的问题,而决定跳转到哪个页面的逻辑依然在Controller或Activity内,这明显违反了功能单一的设计原则,我们可以扩展下Router ,把决定跳转的业务逻辑放置在Router内。
上图的例子中可以看到三个Route:
- Sign In > 首页
- Get a Free Apple ID > 注册页面
- Forgot Apple ID or Password ? > 忘记密码页面
因为用户登录时有可能失败(密码忘记了?),这就多出现一个Route:
- Sign In > 首页 或 忘记密码页面
面临这个场景, 我们可以在Controller里实现以下逻辑:
func loginButtonTapped() {
if shouldChangePassword {
Router.push("myapp://login/changepwd")
} else {
Router.push("myapp://user/home")
}
}
上面代码中的逻辑判断不应属于Controller,Controller内只应包括View相关的或系统的事件回调处理。这时我们可以引进LoginRouter了。
class LoginRouter {
func route(
to routeID: String,
from context: UIViewController,
parameters: Any?)
{
guard let route = LoginVC.Route(rawValue: routeID) else {
return
}
switch route {
case .login:
if shouldChangePassword {
Router.push("myapp://login/changepwd")
} else {
Router.push("myapp://user/home")
}
case .signUp:
Router.push("myapp://login/signup")
case . forgotPasswordScreen:
Router.push("myapp://login/changepwd")
}
}
}
这样在原来的Controller内代码也要做相应修改,注意这里省略了登录状态的传递,如果是MVVM结构可以使用ViewModel, Redux 模式可传递State。具体可iOS 常见架构一览。
class LoginViewController: UIViewController {
enum Route: String {
case login
case signUp
case forgotPassword
}
var router: LoginRouter!
...
func loginButtonTapped() {
router.route(to: Route.login.rawValue, from: self)
}
func signUpTapped() {
router.route(to: Route.signUp.rawValue, from: self)
}
func forgotPasswordTapped() {
router.route(to: Route.forgotPassword.rawValue, from: self)
}
这样我们完全把路由相关代码完全从Controller移出,将来需若改变路由代码,只需修改路由类即可,而不用到处搜索相应的View Controller。
同时我们也完成了Controller的瘦身目标,有兴趣的可以阅读iOS - Controller 瘦身简析。
更多
获取更多内容请关注微信公众号豆志昂扬:
- 直接添加公众号豆志昂扬;
- 微信扫描下图二维码;