加入收藏 | 设为首页 | 会员中心 | 我要投稿 威海站长网 (https://www.0631zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长资讯 > 外闻 > 正文

JavaScript中几乎一切都是对象

发布时间:2021-02-20 13:40:00 所属栏目:外闻 来源:互联网
导读:不过要注意的是,调用它的协程将会在主线程上执行。所以,如果您要对执行结果做一些比较耗时的操作,比如对列表内容进行转换,您要确保这个操作不会阻塞主线程。 注意: Room 使用了自己的调度器在后台线程上进行查询操作。您不应该再使用 withContext(Dispat

不过要注意的是,调用它的协程将会在主线程上执行。所以,如果您要对执行结果做一些比较耗时的操作,比如对列表内容进行转换,您要确保这个操作不会阻塞主线程。

注意: Room 使用了自己的调度器在后台线程上进行查询操作。您不应该再使用 withContext(Dispatchers.IO) 来调用 Room 的 suspend 查询,这只会让您的代码变复杂,也会拖慢查询速度。

Room 的挂起函数是主线程安全的,并运行于自定义的调度器中。

一次性请求模式

这是在 Android 架构组件中使用协程进行一次性请求的完整模式,我们将协程添加到了 ViewModel、Repository 和 Room 中,每一层都有着不同的责任分工。

  • ViewModel 在主线程上启动了协程,一旦有结果后就结束执行;
  • Repository 提供了保证主线程安全的挂起函数;
  • 数据库和网络层提供了保证主线程安全的挂起函数。

ViewModel 负责启动协程,并保证用户离开了相应界面时它们就会被取消。它本身并不会做一些耗时的操作,而是依赖别的层级来做。一旦有了结果,就使用 LiveData 将数据发送到 UI 层。因为 ViewModel 并不做一些耗时操作,所以它是在主线程启动协程的,以便能够更快地响应用户事件。

Repository 提供了挂起函数用来访问数据,它通常不会启动一些生命周期比较长的协程,因为它们一旦启动了便无法取消。无论何时 Repository 想要做一些耗时操作,比如对列表内容进行转换,都应该使用 withContext 来提供主线程安全的接口。

数据层 (网络或数据库) 总是会提供挂起函数,使用 Kotlin 协程的时候要保证这些挂起函数是主线程安全的,Room 和 Retrofit 都遵循了这一点。

在一次性请求中,数据层只提供挂起函数,调用方如果想要获取最新的值,只能再次进行调用,这就像浏览器中的刷新按钮一样。

花点时间让您了解一次性请求的模式是值得,它在 Android 协程中是比较通用的模式,您会一直用到它。

第一个 bug 出现了

在经过测试后,您部署到了生产环境,运行了几周都感觉良好,直到您收到了一个很奇怪的 bug 报告:

标题:🐞 — 排序错误!

错误报告: 当我非常快速地点击排序按钮时,排序的结果偶尔是错的,这还不是每次都能复现的🙃。

您研究了一下,不禁问自己哪里出错了?这个逻辑很简单:

  • 开始执行用户请求的排序操作;
  • 在 Room 调度器中开始进行排序;
  • 展示排序结果。

您觉得这个 bug 不存在准备关闭它,因为解决方案很简单,"不要那么快地点击按钮",但是您还是很担心,觉得还是哪个地方出了问题。于是在代码中加入一些日志,并跑了一堆测试用例后,您终于知道问题出在什么地方了!

看起来应用内展示的排序结果并不是真正的 "排序结果",而是上一次完成排序的结果。当用户快速点击按钮时,就会同时触发多个排序操作,这些操作可能以任意顺序结束。

当启动一个新的协程来响应 UI 事件时,要去考虑一下用户若在上一个任务未完成之前又开始了新的任务,会有什么样的后果。

这其实是一个并发导致的问题,它和是否使用了协程其实没有什么关系。如果您使用回调、Rx 或者是 ExecutorService,还是可能会遇到这样的 bug。

有非常多方案能够解决这个问题,既可以在 ViewModel 中解决,又可以在 Repository 中解决。我们来看看怎么才能让一次性请求按照我们所期望的顺序返回结果。

最佳解决方案:禁用按钮

核心问题出在我们做了两次排序,要修复的话我们可以只让它排序一次。最简单的解决方法就是禁用按钮,不让它发出新的事件就可以了。

这看起来很简单,而且确实是个好办法。实现起来的代码也很简单,还容易测试,只要它能在 UI 中体现出来这个按钮的状态,就完全可以解决问题。

要禁用按钮,只需要告诉 UI 在 sortPricesBy 中是否有正在处理的排序请求,示例代码如下:



(编辑:威海站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读