前言

使用kotlin协程也有一段时间了,给我最大的感受就是完全可以替代Rxjava了,并且写起来更加的简洁。

6月份Retrofit发布的2.6.0版本内部支持了kotlin协程中的挂起(suspend)修饰符,这就意味着我们可以更加方便的用Retrofit结合kotlin协程来实现网络请求了。

之前我都是使用Rxjava2+Retrofit实现网络请求的功能,然后加入了AutoDispose来实现自动解绑以免发生内存泄漏的问题,感兴趣的可以看看AutoDispose代替RxLifecycle优雅的解决RxJava内存泄漏问题

那协程有没有自动解绑的东西呢。当然有了
目前google官方也给我们提供了androidx.lifecycle:lifecycle-viewmodel-ktx的依赖包,给ViewModel中扩展了一个作用域叫viewModelScope

viewModelScope是一个绑定到当前viewModel的作用域 当ViewModel被清除时会自动取消该作用域,所以不用担心内存泄漏为问题

那这样一来,我们完全可以使用Retrofit+Coroutines这个方案来代替之前用Retrofit+Rxjava+AutoDispose的方案了。

话不多说,直接上代码

我在网上找了个公开的API接口 https://www.apiopen.top/novelApi

我们就请求这个接口了

添加依赖

首先是添加需要的依赖包,如下

    implementation 'androidx.appcompat:appcompat:1.1.0'implementation 'androidx.core:core-ktx:1.1.0'implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.1"implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.1"implementation "androidx.lifecycle:lifecycle-extensions:2.1.0"implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0"implementation "com.squareup.okhttp3:okhttp:4.2.0"implementation "com.squareup.retrofit2:retrofit:2.6.1"implementation "com.squareup.okhttp3:logging-interceptor:4.2.0"implementation "com.squareup.retrofit2:converter-gson:2.6.1"

代码

在看下面的代码之前,你可能需要先看一下下面几篇文章,如果你都知道的话 直接跳过即可

ViewModelLiveData 还不是很了解的话先看一下这篇文章
mvp过渡到mvvm(Android 架构组件)

关于一些好用的扩展方法,看一下这个
Kotlin基于RxJava的扩展方法(超级好用)
这里我们主要是看对数据类的扩展,节省一些无用代码

关于Retrofit的工厂类这里我就不放出来了,估计大家的代码都差不多,需要的可以看demo,这里我就不再浪费篇幅,直接用了。

实体类

响应基类

data class BaseResp<T>(var code: Int = 0,var msg: String = "",var `data`: T
)

小说数据实体类

package com.yzq.coroutineretofitmvvm.beanimport com.google.gson.annotations.SerializedNamedata class Fiction(var bid: String = "",var bookname: String = "",var introduction: String = "",@SerializedName("book_info")var bookInfo: String = "",var chapterid: String = "",var topic: String = "",@SerializedName("topic_first")var topicFirst: String = "",@SerializedName("date_updated")var dateUpdated: Int = 0,var author: String = "",@SerializedName("author_name")var authorName: String = "",@SerializedName("top_class")var topClass: String = "",var state: String = "",var readCount: String = "",var praiseCount: String = "",@SerializedName("stat_name")var statName: String = "",@SerializedName("class_name")var className: String = "",var size: String = "",@SerializedName("book_cover")var bookCover: String = "",@SerializedName("chapterid_first")var chapteridFirst: String = "",var chargeMode: String = "",var digest: String = "",var price: String = "",var tag: List<String> = listOf(),@SerializedName("is_new")var isNew: Int = 0,var discountNum: Int = 0,@SerializedName("quick_price")var quickPrice: Int = 0,var formats: String = "",@SerializedName("audiobook_playCount")var audiobookPlayCount: String = "",var chapterNum: String = "",var isShortStory: Boolean = false,var userid: String = "",@SerializedName("search_heat")var searchHeat: String = "",@SerializedName("num_click")var numClick: String = "",@SerializedName("recommend_num")var recommendNum: String = "",@SerializedName("first_cate_id")var firstCateId: String = "",@SerializedName("first_cate_name")var firstCateName: String = "",var reason: String = ""
)

定义请求接口

这个没什么好说的,需要注意的就是我们的方法前面用 suspend 修饰

interface ApiService {@GET("https://www.apiopen.top/novelApi")suspend fun getFictions(): BaseResp<List<Fiction>>
}

用于解析响应数据的扩展方法

/*数据解析扩展函数*/
fun <T> BaseResp<T>.dataConvert(): T {if (code == 200) {return data} else {throw Exception(msg)}
}

ViewModel

注释也很详细了,这里就不多说了

class NetViewModel : ViewModel() {var fictions = MutableLiveData<List<Fiction>>()fun getFictions() {/*viewModelScope是一个绑定到当前viewModel的作用域  当ViewModel被清除时会自动取消该作用域,所以不用担心内存泄漏为问题*/viewModelScope.launch {try {/*dataConvert扩展函数可以很方便的解析出我们想要的数据  接口很多的情况下下可以节省不少无用代码*/val data =RetrofitFactory.instance.getService(ApiService::class.java).getFictions().dataConvert() /*给LiveData赋值  ui会自动更新*/fictions.value = data} catch (e: Exception) {/*请求异常的话在这里处理*/e.printStackTrace()Log.i("请求失败", "${e.message}")}}}}

Activity

Activity中代码就很简单了,主要就是创建ViewModel示例,更新ui


class MainActivity : AppCompatActivity() {private lateinit var netViewModel: NetViewModeloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)/*创建viewmodel*/netViewModel = ViewModelProviders.of(this).get(NetViewModel::class.java)btn.setOnClickListener {/*请求数据*/netViewModel.getFictions()}/*数据发生变化时更新ui*/netViewModel.fictions.observe(this, Observer {tv.text = Gson().toJson(it)})}
}

下面我们来看看运行结果:

可以看到,网络请求的功能已经实现了。

那对比RxJava的实现方式,你觉得哪种方式更好呢?

好了,本篇文章到此结束。

demo


如果你觉得本文对你有帮助,麻烦动动手指顶一下,算是对本文的一个认可,如果文中有什么错误的地方,还望指正,转载请注明转自喻志强的博客 ,谢谢!

Retrofit+kotlin Coroutines(协程)+mvvm(Jetpack架构组件)实现更简洁的网络请求相关推荐

  1. kotlin coroutines 协程教程-入门用法

    kotlin coroutines 协程教程-入门用法 Coroutine 协程,是kotlin 上的一个轻量级的线程库,对比 java 的 Executor,主要有以下特点: 更轻量级的 api 实 ...

  2. Android MVVM + Retrofit + OkHttp + Coroutine 协程 + Room + 组件化架构的Android应用开发规范化架构

    BaseDemo 介绍 BaseDemo 是Android MVVM + Retrofit + OkHttp + Coroutine 协程 + Room + 组件化架构的Android应用开发规范化架 ...

  3. Kotlin 之 协程

    初识协程,启动取消协程,Flow异步流,协程并发 目录 (一)初识协程 协程是什么? Android中协程解决了什么问题? 协程的挂起与恢复 挂起和阻塞 协程的调度器 Dispatchers 任务泄露 ...

  4. Kotlin的协程与生命周期

    文章目录 一.前言 二.引入依赖 三.代码示例 1.基础用法 2.repeatOnLifecycle 3.flowWithLifecycle 4.lifecycle.whenCreated.lifec ...

  5. 十一、kotlin的协程(一)

    theme: Chinese-red 学习的前提 java线程需要大概知道点 协程是线程执行的任务, 协程和用户线程的区别在于, 协程背靠强大的编译器, 协程有专属于协程的调度器和一堆方便好用的函数, ...

  6. Kotlin高级协程

    Kotlin高级协程 一.前言 二.先从线程说起 三.协程的设计思想 四.协程特点:优雅的实现移步任务 五.协程基本使用 六.协程和线程相比有什么特点,如何优雅的实现异步任务 一.前言 在文章正式上干 ...

  7. 【对比Java学Kotlin】协程简史

    文章目录 一.概念释义 1.1 协程定义 1.2 与线程的关系 1.3 协程简史 二.种类划分 2.1 按调用栈分类 2.2 按调度方式分类 三.异步编程 3.1 多线程 3.2 回调 3.3 Pro ...

  8. Kotlin(3)-协程和操作符重载,Java程序员秋招三面蚂蚁金服

    Kotlin 文件和类不存在一对一关系 共生体 继承 修饰符 空指针问题 正文 重难点 协程 想了很久,关于协程的内容,在官网上确实有很多内容,基础知识概念,基本使用,以及 流操作,通道,异常处理,并 ...

  9. 十一、kotlin的协程 - 缓存、volatile、内存屏障和cas(四) --- 跑题篇

    本章写着写着就跑题了, 又不舍得删除, 新手看 # 协程的共享变量安全问题简单入门和## volatile 不保证原子性部分代码, 其他可以不看, 太乱, 也没用 协程的共享变量安全问题简单入门 在使 ...

最新文章

  1. SpringCloudAlibaba:Nacos实现原理详解
  2. 5G信令(就是用户身份信息)——手机开机后,先从USIM中读取之前运营商分配的临时身份信息GUTI/TMSI,发送携带该身份信息的信令给基站,请求接入运营商网络。...
  3. 排序算法----快速排序(数组形式)
  4. 干货|Flutter 原理与闲鱼深度实践
  5. linux 上传文件 rz命令 提示command not found 解决方法
  6. 在.NET中读写INI文件 ——兼谈正则表达式的应用
  7. 首个月球旅客!SpaceX将送普通人上太空,马斯克暗示首单来自日本
  8. 【三支火把】--- 关于UEFIPCD的总结介绍
  9. WPS如何按单元格背景颜色求和
  10. 099 《少有人走的路:心智成熟的旅程》简记
  11. 【知识总结】数学必修二立体几何总结
  12. console.log(0.2+0.4===0.6)// true or false??
  13. slamugv小车使用说明--1材料准备
  14. C4996:'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead.
  15. 软件设计师(中级)详细复习过程总结
  16. JVM中的对象探秘(三)- 对象的实例数据与对齐填充
  17. 蓝桥杯十大常见天阶功法——虫之呼吸.贰之型.二分
  18. 计算机病毒作文300,我vs电脑的作文300字
  19. 【OCR识别】如何实现实时视频文案转文字、音频歌词字幕提取和翻译?视频提取文字,动态识别提取文字并导出Excel...
  20. jsp连接数据库实现用户登录功能

热门文章

  1. 典型工业数据分析场景解读:机械设备振动监测和故障诊断
  2. python中的“ ... ”
  3. php网页有图片加载慢,网页加载加速 之 图片延迟加载
  4. java期末_Java期末总结
  5. Very Suspicious (思维)
  6. 【CV作业02】图像灰度值变换+UI
  7. 2022年计算机视觉领域五大发展趋势
  8. npm 使用淘宝镜像及切换回官方源
  9. 别再误会碎片化阅读了
  10. tomcat配置前端静态文件gzip压缩