kotlin 协程最佳实践-android官网

代码 代码 1495 人阅读 | 0 人回复

<
协程最好理论 android民网地点

那些理论可让您的法式正在利用协程的时分愈加的易扩大战易测试
1.注进调理器

没有要正在创立一个协程的时分大概挪用withContext,硬编码去指定调理器 好比如许的
  1. class NewsRepository {
  2.     // DO NOT use Dispatchers.Default directly, inject it instead
  3.     suspend fun loadNews() = withContext(Dispatchers.Default) { /* ... */ }
  4. }
复造代码
而该当举办注进
  1. class NewsRepository(
  2.     private val defaultDispatcher: CoroutineDispatcher = Dispatchers.Default
  3. ) {
  4.     suspend fun loadNews() = withContext(defaultDispatcher) { /* ... */ }
  5. }
复造代码
缘故原由:依靠注进的形式可让您正在测试的时分简单改换调理器 详细参考Android中浅易的协程
2. 挂起函数正在完成的时分,该当包管对主线程是宁静的

好比如许的:
  1. suspend fun fetchLatesNews():ListArtical{
  2.     withContext(Dispatchers.IO){
  3.     }
  4. }
复造代码
主线程挪用的时分
  1. suspend operator fun updateContent(){
  2.     val news = fetchLatesNews()
  3. }
复造代码
如许能够包管您的App是易扩大的,类挂起办法挪用的时分,没有需求担忧线程是正在哪一个状况调理的,由详细完成类中的办法去确保线程调理的宁静
3. viewModle 该当来创立一个协程

viewModle更该当来创立一个协程,而没有是来表露一个suspend办法。 好比该当是如许:
  1. //示例代码,viewModle内乱来创立一个协程
  2. class LastestNewsViewModel{
  3.     //内乱部保护了一个可察看的带形态的数据
  4.     private val _uiState = MutableStateFlow<LatestNewsUiState>(LatestNewsUiState.Loading)
  5.     val uiState:StateFlow<LatestNewsUiState> = _uiState
  6.     //重面去了,那里没有是一个suspend办法
  7.     fun loadNews(){
  8.         viewModleScope.lanuch{
  9.             val lastestNewsWithAuthors = getLatestNewsWithAuthors()
  10.             _uiState.valule = LastestNewUiState.Success(lastestNewsWithAuthors)
  11.         }
  12.     }
  13. }
复造代码
而没有是如许的
  1. class LastestNewsViewModel():ViewModel{
  2.     //这类是间接返回了一个suspend办法
  3.     suspend fun loadNews() = getLatestNewsWithAuthors()
  4. }
复造代码
除非没有需求挪用明白数据流的形态,而只需求收射一个零丁的数据。(小我私家大白,是连结viewModle中的界说,保护一个可察看的带形态的数据,而没有是间接扔本初数据出去)
4.没有要表露可修正的参数范例

该当对其他类表露不成修正的的范例,如许一切可变范例数据的变动皆集合正在一个类里,假设有题目的时分,更简单调试(也是迪米特准绳) 好比该当是如许的
  1. class LastestNewsViewModel : ViewModel{
  2.     //可修正范例
  3.     private val _uiState = _MutalbeStateFlwow(LastestNewsViewModel.Loading)
  4.     //对中表露不成修正范例数据(对中没有供给修正功用)
  5.     val uiState : StateFlow<LatestNewsUiState> = _uiState
  6. }
复造代码
5. 数据战营业层该当表露挂起函数 或 Flow

数据层战营业层凡是需求表露办法,来施行一次性的挪用大概需求持续吸取数据的变革,这时候候该当供给为一次性挪用供给挂起函数 大概 供给Flow去帮手察看数据的变革操作 好比如许的:
  1. class ExampleRepository{
  2.     //为一次性的挪用供给 suspend办法
  3.     suspend fun makeNetworkRequest(){}
  4.     //为一需求察看的数据供给Flow工具
  5.     fun getExamples():Flow<Example>{}
  6. }
复造代码
最好的理论可使挪用者凡是是营业层,能够掌握营业的施行战性命周期的运转,而且正在需求的时分能够打消使命
6. 正在营业战数据层创立协程

正在数据战营业层需求创立协程的缘故原由大要有没有几的缘故原由,下边是一些大要的选项


  • 假设协程的使命是相关的,且只正在用户正在当前界里时才显现,那末它需求联系关系挪用者的性命周期,那个挪用者凡是便是ViewModel,正在这类 状况下, 该当利用coroutineScope 战 supervisorScope
示例代码:
  1. class GetAllBooksAndAuthorsUseCase(
  2.     private val booksRepository:BooksRepository,
  3.     private val authorsRepository:AuthorsRepository,
  4.     private val defaultDispatcher:CoroutineDispatcher = Dispatchers.Default
  5. ){
  6.     suspend fun getBookdAndAuthors():BookAndAuthors{
  7.         //仄止的状况需求等候成果,册本列表战做者列表需求同时筹办好以后再返回
  8.         return coroutineScope{
  9.             val books = async(defaultDispatcher){
  10.                 booksRepository.getAllBooks()
  11.             }
  12.             val authors = async(defaultDispatcher){
  13.                 authorsRepository.getallAuthors()
  14.             }
  15.             //筹办好数据以后再返回
  16.             BookAndAuthors(books.await(),authors.await())
  17.         }
  18.     }
  19. }
复造代码


  • 假设那个使命是正在App开启时期需求施行,那个使命也没有绑定到某一个详细的界里,这时候候使命是需求正在超越挪用者的性命周期的,这类场景下,需求用到
external 的 CoroutineScope ,详细可参考 协程设想形式之使命不该该被打消
参考示例代码:
  1. class ArticalesRepository(
  2.     private val articlesDataSource: ArticlesDataSource,
  3.     private val externalScope:CoroutineScope,
  4.     private val defaultDispatcher:CoroutineDispatcher = Dispatchers.Default
  5. ){
  6.     //那个场景是如许的,即便我们分开的屏幕,也期望那个预订操纵是可以被完好施行的,那末那使命斋要正在内部域开启一个新的协程里去完成那wh
  7.     suspend fun bookmarkArtical(artical:Article){
  8.         externalScope.lanuch(defaultDispatcher){
  9.             articlesDataSource.bookmarkArticle(article)
  10.         }.join() //等候协程施行终了
  11.     }
  12. }
复造代码
分析: 内部域需求被一个比当前界里的性命周期更少的一个类去创立,好比道 Application大概是一个navigatin grah的ViewModel
7. 制止利用GlobalScope齐局感化域

便像最好理论里边的注进调理器,假设用了GlobalScope,那便是正在类里边利用硬编码,大要会有以下几个背里影响


  • 硬编码。
  • 易以测试
8. 协程需求能够被打消

打消操作也是一种协程的操作,意义是道当协程被打消的时分,协程并出有间接被打消,除非它正在 挂起 大概 有打消操作,假设您的协程是正在操作一个壅闭的操作,需求确保协程是半途能够被打消的。 举个例子,假设您正正在读与多个文件,需求正在读与每一个文件之前,查抄下协程能否曾经被打消了,一个查抄协程能否被打消的办法便是 挪用 ensureActivite办法,(大概另有isActive可用) 参考示例代码:
  1.     someScope.lanuch{
  2.         ensureActive()//查抄协程能否曾经被打消
  3.         readFile(file)
  4.     }
复造代码
更多详细的形貌疑息能够参考 打消协程
9. 协程的非常处置

假设协程扔出的非常处置不妥,大要会招致您的App瓦解。假设非常呈现了,便正在协程里便捕捉好非常并举办处置
参考示例代码:
  1. class LoginViewModel(
  2.     private val loginRepository:LoginRepository
  3. ):ViewModel(){
  4.     fun login(username:String,token:String){
  5.         viewModleScope.lanuch{
  6.             try{
  7.                 loginRepository.login(username,token)
  8.                 //告诉界里登录胜利
  9.             }catch(error:Throwable){
  10.                 //告诉view 登录操纵失利
  11.             }
  12.         }
  13.     }
  14. }
复造代码
更多协程非常的处置,大概其他场景需求用到CoroutineExceptionHandler,能够参考 协程非常处置

免责声明:假如进犯了您的权益,请联络站少,我们会实时删除侵权内乱容,感谢协作!
1、本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,按照目前互联网开放的原则,我们将在不通知作者的情况下,转载文章;如果原文明确注明“禁止转载”,我们一定不会转载。如果我们转载的文章不符合作者的版权声明或者作者不想让我们转载您的文章的话,请您发送邮箱:Cdnjson@163.com提供相关证明,我们将积极配合您!
2、本网站转载文章仅为传播更多信息之目的,凡在本网站出现的信息,均仅供参考。本网站将尽力确保所提供信息的准确性及可靠性,但不保证信息的正确性和完整性,且不对因信息的不正确或遗漏导致的任何损失或损害承担责任。
3、任何透过本网站网页而链接及得到的资讯、产品及服务,本网站概不负责,亦不负任何法律责任。
4、本网站所刊发、转载的文章,其版权均归原作者所有,如其他媒体、网站或个人从本网下载使用,请在转载有关文章时务必尊重该文章的著作权,保留本网注明的“稿件来源”,并自负版权等法律责任。
回复 关闭延时

使用道具 举报

 
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则