前言

使用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. 利用计算机技术教学图片,教育教学论文 科学学科如何利用计算机技术提高教学效率.doc...
  2. iOS 新窗口在最上层
  3. python常用内置模块-python 常用内置模块使用
  4. Python eval函数用法简介
  5. Android 编译 SDK
  6. 系统架构设计师考试999999999999
  7. 人工智能的本源与展望:从亚里士多德到平行智能
  8. C#LeetCode刷题之#26-删除排序数组中的重复项(Remove Duplicates from Sorted Array)
  9. 使用ByteArray及AMF来提高Data Object的操作效率
  10. 程序员分析了 50 万条拼多多商品数据,告诉你到底是消费升级还是降级!
  11. JavaScript--百度地图那些坑
  12. [na]802.1x协议无线认证协议dot1x有线认证实验
  13. cvSplit(),cv图像颜色通道分割和融合
  14. 西电计算机网络ppt,《西安电子科技大学》PPT课件
  15. python 论文降重_我用Python写了一个论文降重工具-Go语言中文社区
  16. vim中文乱码问题解决方式
  17. 将base64指纹编码输出为指定大小的图片
  18. 吴恩达 02.改善深层神经网络:超参数调试、正则化以及优化 第一周作业
  19. Gensim学习笔记-1--理解corpora.Dictionary
  20. echarts legend图例显示数值和百分比

热门文章

  1. ST202EB_15KV ESD保护5V RS-232收发器,温度范围[-40℃, 85℃]——科时进商城
  2. 计算机模拟虚拟筛选操作流程
  3. 《缠中说禅108课》76:逗庄家玩的一些杂史 2
  4. 老电脑安装XP时遇到问题的总结
  5. 软考中级 真题 2016年上半年 系统集成项目管理工程师 应用技术 下午试卷
  6. wsl2 设置端口映射
  7. 微信小程序从后台拿数据并成功展示到前台——demo
  8. LeetCode 第 993 题:二叉树的堂兄弟结点
  9. phpStudy激活码
  10. 百汇BCR:为什么要使用外汇模拟交易软件?有什么好处?