Kotlin-Retrofit2和Rxjava2的网络封装,展示Github的用户信息

2023-11-08

目录

开始

1.先添加依赖 

2.封装请求类

3.RESTful API请求响应的处理

4.线程与生命周期

5.使用

效果如下:


开始

1.先添加依赖 

//Retrofit相关
    implementation(['com.squareup.okhttp3:logging-interceptor:3.9.0',//用于查看http请求时的log
                    'com.squareup.retrofit2:retrofit:2.3.0',
                    'com.squareup.retrofit2:adapter-rxjava2:2.3.0',
                    'com.squareup.retrofit2:converter-gson:2.3.0'])

//RxJava相关
    implementation(['io.reactivex.rxjava2:rxandroid:2.0.1',
                    'io.reactivex.rxjava2:rxjava:2.1.3'])
     

//RxLifecycle相关
    implementation(['com.trello.rxlifecycle2:rxlifecycle-kotlin:2.2.0',
                    'com.trello.rxlifecycle2:rxlifecycle-components:2.2.0'])

2.封装请求类

 Retrofit简单封装秉承RxJava的链式调用风格,也为了方便每一个API的调用操作,创建了一个单例类ApiClient,具体如下:

class ApiClient private constructor() {
    lateinit var service: GitHubService

    private object Holder {
        val INSTANCE = ApiClient()
    }
    companion object {
        val instance by lazy { Holder.INSTANCE }
    }
    fun init() {//在Application的onCreate中调用一次即可
        val okHttpClient = OkHttpClient().newBuilder()
                //输入http连接时的log,也可添加更多的Interceptor
                .addInterceptor(HttpLoggingInterceptor().setLevel(
                        if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY
                        else HttpLoggingInterceptor.Level.NONE
                )).build()
        val retrofit = Retrofit.Builder()
                .baseUrl("https://api.github.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(okHttpClient)
                .build()
        service = retrofit.create(GitHubService::class.java)
    }
}

  在这里使用GitHubAPI作为测试,GitHubService如下:

interface GitHubService {
    //请添加相应的`API`调用方法
    @GET("users/{user}/repos")
    fun listRepos(@Path("user") user: String): Observable<List<Repo>>//每个方法的返回值即一个Observable
}

上面的Repo即一个简单的Kotlin数据类,由于字较多,就不贴出来了,具体可去Demo查找。

3.RESTful API请求响应的处理

API的响应返回形式有很多种,此处介绍标准RESTful APIGitHub提供的API即标准RESTful API

先在values写一下错误描述:

 <resources>
    <string name="service_error">服务器出错</string>
    <string name="not_found">请求的资源不存在</string>
    <string name="timeout">请求超时</string>
    <string name="unexpected_error">未知错误</string>
    <string name="network_wrong">网络有问题</string>
</resources>

RESTful API的请求响应主要处理状态码与数据体,具体封装如下:

abstract class ApiResponse<T>(private val context: Context) : Observer<T> {
    abstract fun success(data: T)
    abstract fun failure(statusCode: Int, apiErrorModel: ApiErrorModel)


    override fun onSubscribe(d: Disposable) {
        LoadingDialog.show(context)
    }

    override fun onNext(t: T) {
        success(t)
    }

    override fun onComplete() {
        LoadingDialog.cancel()
    }

    override fun onError(e: Throwable) {
        LoadingDialog.cancel()
        if (e is HttpException) {//连接服务器成功但服务器返回错误状态码
            val apiErrorModel: ApiErrorModel = when (e.code()) {
                ApiErrorType.INTERNAL_SERVER_ERROR.code ->
                    ApiErrorType.INTERNAL_SERVER_ERROR.getApiErrorModel(context)
                ApiErrorType.BAD_GATEWAY.code ->
                    ApiErrorType.BAD_GATEWAY.getApiErrorModel(context)
                ApiErrorType.NOT_FOUND.code ->
                    ApiErrorType.NOT_FOUND.getApiErrorModel(context)
                else -> otherError(e)
            }
            failure(e.code(), apiErrorModel)
            return
        }
        val apiErrorType: ApiErrorType = when (e) {//发送网络问题或其它未知问题,请根据实际情况进行修改
            is UnknownHostException -> ApiErrorType.NETWORK_NOT_CONNECT
            is ConnectException -> ApiErrorType.NETWORK_NOT_CONNECT
            is SocketTimeoutException -> ApiErrorType.CONNECTION_TIMEOUT
            else -> ApiErrorType.UNEXPECTED_ERROR
        }
        failure(apiErrorType.code, apiErrorType.getApiErrorModel(context))
    }

    private fun otherError(e: HttpException) =
            Gson().fromJson(e.response().errorBody()?.charStream(), ApiErrorModel::class.java)
}

说明:
1.每个响应继承Observer,其中的泛型以适配返回的不同的数据体;
2.定义两个抽象方法successfailure,在使用的时候只需关注成功和失败这两种情况;
3.在onSubscribe即开始请求的时候显示Loading,在请求完成或出错时隐藏;
4.在onNextObserver成功接收数据后直接调用success,在调用处可直接使用返回的数据;
5.在onError即请求出错时处理,此处包含两种情况:连接服务器成功但服务器返回错误状态码、网络或其它问题。

这个是读条时的LoadingDialog代码:

dialog_loading.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ProgressBar
        style="@android:style/Widget.ProgressBar.Inverse"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center" />

</LinearLayout>

styles:

    <style name="LoadingDialog" parent="@android:style/Theme.Dialog">
        <item name="android:windowFrame">@null</item>
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowIsTranslucent">false</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:backgroundDimEnabled">false</item>
    </style>

LoadingDialog:

object LoadingDialog {
    private var dialog: Dialog? = null

    fun show(context: Context) {
        cancel()
        dialog = Dialog(context, R.style.LoadingDialog)
        dialog?.setContentView(R.layout.dialog_loading)
        dialog?.setCancelable(false)
        dialog?.setCanceledOnTouchOutside(false)
        dialog?.show()
    }
    fun cancel() {
        dialog?.dismiss()
    }
}

在错误处理中,定义了一个枚举类ApiErrorType,用于列举出服务器定义的错误状态码情况:

enum class ApiErrorType(val code: Int, @param:StringRes private val messageId: Int) {
    //根据实际情况进行增删
    INTERNAL_SERVER_ERROR(500, R.string.service_error),
    BAD_GATEWAY(502, R.string.service_error),
    NOT_FOUND(404, R.string.not_found),
    CONNECTION_TIMEOUT(408, R.string.timeout),
    NETWORK_NOT_CONNECT(499, R.string.network_wrong),
    UNEXPECTED_ERROR(700, R.string.unexpected_error);

    private val DEFAULT_CODE = 1
    fun getApiErrorModel(context: Context): ApiErrorModel {
        return ApiErrorModel(DEFAULT_CODE, context.getString(messageId))
    }
}

还定义了一个错误消息的的实体类ApiErrorModel(在Kotlin中即为一个数据类),用于包含错误信息提示用户或服务器返回的错误信息以提示开发人员:

data class ApiErrorModel(var status: Int, var message: String)

4.线程与生命周期

RxJava的一大特色即方便的线程切换操作,在请求API中需要进行线程的切换,通常是以下形式(伪代码):

observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())

但每个请求都写一段这个,显得特别麻烦,所以进行以下简单封装:

object NetworkScheduler {
    fun <T> compose(): ObservableTransformer<T, T> {
        return ObservableTransformer { observable ->
            observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
        }
    }
}

Android中,当一个Activity在调APIonDestroy了,需要取消请求,所以此处引入了RxLifecycle进行管理:
Activity继承RxAppCompatActivity后,在observable的调用链中加入.bindUntilEvent(this, ActivityEvent.DESTROY)即可

5.使用

以上准备工作完成后,即可开始使用:
首先在Application中初始化ApiClient

class App : Application() {
    override fun onCreate() {
        super.onCreate()
        ApiClient.instance.init()
    }
}

在需要的地方使用ApiClient,如本文Demo,点击按钮时,请求数据,成功后用TextView显示出来:

class MainActivity : RxAppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        submit.setOnClickListener { fetchRepo() } //按钮点击事件
    }
    private fun fetchRepo() {
        //链式调用
        ApiClient.instance.service.listRepos(inputUser.text.toString()) //GitHubService中的方法
                .compose(NetworkScheduler.compose())                         //线程切换处理
                .bindUntilEvent(this, ActivityEvent.DESTROY)        //生命周期管理
                .subscribe(object : ApiResponse<List<Repo>>(this) {              //对象表达式约等于Java中的匿名内部类
                    override fun success(data: List<Repo>) {                     //请求成功,此处显示一些返回的数据
                         userName.text = data[0].owner.login   //用户名
                        repoName.text = data[0].name            //仓库名
                        description.text = data[0].description  //描述
                        url.text = data[0].html_url         //url
                    }
                    override fun failure(statusCode: Int, apiErrorModel: ApiErrorModel) {
                        Toast.makeText(this@MainActivity, apiErrorModel.message, Toast.LENGTH_SHORT).show()
                    }
                })
    }
}

效果如下

Demo地址:https://github.com/qingyinz/RxjavaRetrofitDemo3
参考链接:http://www.jianshu.com/p/c66d50cd14ee

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Kotlin-Retrofit2和Rxjava2的网络封装,展示Github的用户信息 的相关文章

  • redis 缓存击穿 看一篇成高手系列3

    什么是缓存击穿 在谈论缓存击穿之前 我们先来回忆下从缓存中加载数据的逻辑 如下图所示 因此 如果黑客每次故意查询一个在缓存内必然不存在的数据 导致每次请求都要去存储层去查询 这样缓存就失去了意义 如果在大流量下数据库可能挂掉 这就是缓存击穿
  • 自己实现c++ list模板类,亲测可用

    双向链表模板类 dlist h ifndef DLIST H define DLIST H include
  • 秋招-准备计划

    秋招 准备计划 基本信息 时间 9月 10月 岗位 java后端开发 目标 中厂 大厂 有高用户量的项目 企业优先 准备 简历 基本信息 获奖情况 项目经历 实习经历 笔试 算法与数据结构 面试 Java篇 基本知识 JVM JUC多线程
  • SQLserver分页 高效率

    SQL Server 存储过程的分页 这个问题已经讨论过几年了 很多朋友在问我 所以在此发表一下我的观点建立表 CREATE TABLE TestTable ID int IDENTITY 1 1 NOT NULL FirstName nv
  • 什么是云计算,云计算的基本原理是什么?

    云计算 cloudcomputing 分布式计算技术的一种 其最基本的概念 是透过网络将庞大的计算处理程序自动分拆成无数个较小的子程序 再交由多部服务器所组成的庞大系统经搜寻 计算分析之后将处理结果回传给用户 透过这项技术 网络服务提供者可
  • 在偏远乡村感受中国电信优厚服务

    春节期间 笔者在家使用中国电信天翼上网卡的过程中发现 目前中国电信的3G网络覆盖在偏远乡村还不是很到位 不过在3G市场的激烈竞争中 运营商的服务意识却有着明显的提升 笔者从北京回家过年 在江西南昌市的一家电信营业厅购买了3G上网卡 当时得知
  • Vue3引用Dplayer播放器播放m3u8,hls播放协议

    一 安装 npm安装Dplayer npm install S Dplayer yarn安装Dplayer yarn add Dplayer 播放协议为 hls 安装hls npm install hls js S 二 代码 我用的是vue
  • sed 命令的高级用法

    编辑命令 d 删除 p 显示模式空间的内容 a text 在行后面追加文本 支持使用 n实现多行追加 i text 在行前面插入文本 支持使用 n实现多行插入 c text 替换行为单行或多行文本 w path to somefile 保存
  • 查看服务器信息

    1 查看 CPU 物理个数 grep physical id proc cpuinfo sort u wc l 2 查看 CPU 核心数量 grep core id proc cpuinfo sort u wc l 3 查看 CPU 线程数
  • MATLAB教学_09影像处理二

    本文视频地址 https www bilibili com video av68228488 p 9 主要学习了初阶影像处理 有三个内容 图像阈值 背景预测 相关连的标签 计算米粒颗数 先将图片二值化 那么有米粒的区域应该是1 而没有的地方
  • [Leetcode] 19. 删除链表的倒数第N个节点

    题目描述 给定一个链表 删除链表的倒数第 n 个节点 并且返回链表的头结点 示例 给定一个链表 1 gt 2 gt 3 gt 4 gt 5 和 n 2 当删除了倒数第二个节点后 链表变为 1 gt 2 gt 3 gt 5 说明 给定的 n
  • 【满分】【华为OD机试真题2023B卷 JAVA&JS】计算误码率

    华为OD2023 B卷 机试题库全覆盖 刷题指南点这里 计算误码率 知识点双指针 时间限制 1s 空间限制 256MB 限定语言 不限 题目描述 误码率是最常用的数据通信传输质量指标 它可以理解为 在多少位数据中出现一位差错 移动通信网络中
  • activiti学习(五)——执行监听器与任务监听器的基本使用

    本文介绍执行监听器与任务监听器的基本原理和使用方法 当流程途径连线或者节点的时候 会触发对应的事件类型 执行监听器与任务监听器在生产中经常会用在几个方面 动态分配节点处理人 通过前一个节点设置的变量 在运行到下一个节点时设置对应的处理人 当
  • Python安装tar.gz格式文件方法详解

    这篇文章主要介绍了Python安装tar gz格式文件方法详解 文中通过示例代码介绍的非常详细 对大家的学习或者工作具有一定的参考学习价值 需要的朋友可以参考下 有的库没有找到对应的 whl格式文件 只有 tar gz格式文件 接下来总结下
  • STM 32——TIM定时器频率测量

    STM 32 TIM定时器频率测量 1 定时器不同工作模式的配置 在使用STM32进行脉冲频率测量时 免不了会碰上TIM定时器的配置问题 这里做一个简单介绍 1 1计数器模式 首先我们选择内部时钟 PCLK 作为定时器的时钟源 PHB总线时
  • 小文件通过接口参数传递

    文件通过base64转换的字符 private static void updateFileInfo File file DocumentInfo docInfo throws IOException ArchiveException Da
  • 目标检测之FCOS算法分析

    网络结构 图片来自原论文 FCOS Fully Convolutional One Stage Object Detection 在ResNet50 Backbone中 C 3 C 4 C
  • Appium自动化框架从0到1之 公共方法的封装

    在写测试用例的时候 最常用的就是方法的调用 我们在这里 把公共方法封装到一个文件中 这样以后需要使用 直接调用这个方法就可以了 直接上代码 common func py coding utf 8 auth carl DJ time 2020
  • HTML基础(新手入门教程)

    学习笔记 HTML基础 前言 勤做笔记不仅可以让自己学的扎实 更重要的是可以让自己少走弯路 有人说 再次翻开笔记是什么感觉 我的回答是 初恋般的感觉 或许笔记不一定十全十美 但肯定会让你有种初恋般的怦然心动 本章着重复习Html的基础内容

随机推荐

  • 计算机网络-详细版

    鉴于有人需要离线版的PDF文档 这里给出本文章的PDF版本 下载地址如下 https pan itnxd cn 123Pan csdn share computer network pdf 一 计算机网络体系结构 0 脑图 1 计算机网络概
  • 一键开关电路设计(一)

    一键开关电路 一 一 功能需求提出 在一些电子产品中 列举 按键的开关机是比不可少的 比如有点按开关机 长按2s短按2s关机 或者长短按相结合来开关机 这里 我分享本人在开发过程中用到的开关机电路 可通过具体开关芯片的选择来实现上面提到的所
  • 操作系统win7与win10的区别介绍

    转自 微点阅读 https www weidianyuedu com 我们都知道Win7跟Win10都属于微软推出的电脑操作系统 这两款操作系统都有着非常鲜明的特点 而且也都有着各自的喜爱者 但是没有任何一款电脑系统是十全十美的 Win7
  • R语言——自定义函数求置信区间

    求单正态均值mu的置信区间 参数依次为置信水平alpha 正态样本x 已知总体方差 默认为未知 mu lt function alpha x sigma NA n lt length x meanx lt mean x if is na s
  • VC++6.0下新建工程中有17个选项,都是做什么用的?

    要理解每种工程的作用需要很多基础知识 简要的一下 1 ATL COM AppWizard 用来新建一个COM组件的向导 比如WORD里用的公式编辑器就是一个COM组件 2 Cluster Resource Type Wizard 群集资源类
  • 二叉树深度的计算

    1 最大深度 根节点到最远叶子节点路径上的节点数 def maxdepth root if not root return 0 if not root rchild and not root lchild return 1 else ml
  • 绿色校园建设

    王兰 安科瑞电气股份有限公司 上海嘉定 201801 摘要 伴随当前环保理念的不断发展 绿色节能理念也在逐步深入校园 为响应国家建设节约型校园的号召 本文以校园智能化综合能效管理平台建设为主题 介绍了平台建设方案 比较了某高校平台建设前后学
  • 美图赶上了AIGC浪潮?

    8月28日 美图公司 1357 HK 正式披露了2023中期业绩 报告期内 公司实现总收入12 61亿元 人民币 下同 同比增长29 8 经调整后归属于母公司权益持有人的净利润1 51亿元 同比增长320 4 从财报上看 美图公司上半年的收
  • python+pywinauto+lackey实现pc端exe自动化

    python pywinauto lackey实现PC端exe自动化 欢迎阅读 框架介绍 环境搭建 Tim自动化 完整代码 写在最后 欢迎阅读 最近一年多一直在从事PC端exe的测试 也是趁着闲余时间 调研了下exe的自动化 核心框架为py
  • 剪绳子(剑指offer 14-1题)

    这道题我拿到之后觉得第一个比较麻烦的点就是分成多少段是不确定的 处理起来就比较抽象 于是自然联想到分段数处理 于是我构建了一个函数getMax int n int i 它用来求长为n的绳子分成i段的最大积 然后在调用处循环每一个可能的i 取
  • 国内最强推荐系统,保姆级学习路线!!(含时间分配规划)

    最近秋招快要结束了 然后一直有很多小伙伴经常在后台私信我计算机专业关于学习路线的问题 可能还是因为没有真正工作而感到迷茫 而我也作为科班生一路走来 真的深知如果没有一个明确的方向 真的很容易走弯路 浪费大把的时间 了解我的小伙伴知道 我毕业
  • 使用UIUC数据集进行汽车检测

    第一步骤 下载数据集 https pan baidu com s 1tk10m8fh 7 MT4NJ29my4g 密码 wdzr 第二步骤 编写代码 如下 import cv2 import numpy as np from os path
  • latex±号_latex中数学符号

    latex中数学符号 常见数学中的特殊符号 缺失 latex中符号3610 9 alpha alfa 阿耳法 beta beta 贝塔 gamma gamma 伽马 deta delta 德耳塔 epsilon epsilon 艾普西隆 z
  • console.writeline($“{}{}“);

    console writeline 作用是将 内容当做表达式 例如 class MyClass public int val 20 class Program static void MyMethod MyClass f1 int f2 f
  • python字典和集合属于无序序列吗_python-序列、集合及字典

    组合数据类型 1 集合类型 集合是多种元素的无序组合 元素独一性 集合用大括号 表示 元素用 分隔 用set函数建立 A set python123 p y t h o n 1 2 3 集合操作符 集合有四种基础运算方法 并 交 差 补 S
  • 关于pads生产文件的导出

    1 solder mask solder mask 是阻焊层出的是负片 它的设置一般如图所示 这个是一般常规设置 如果器件焊盘已经专门做了阻焊焊盘 则可以按如图所示设置 如果选择top层焊盘 设备设置可以选择缩放为4 如果选择solder
  • EVE-NG网卡桥接,带您走进更高级的实验

    原帖地址 http www mamicode com info detail 1819599 html 一 给EVE NG添加虚拟的物理网卡 不管什么样的网卡 方法都类似 为什么说是虚拟的物理网卡呢 这个VMnet1网卡本身就是虚拟出来的
  • 一篇文章让你了解大数据挖掘技术

    大数据如果想要产生价值 对它的处理过程无疑是非常重要的 其中大数据分析和大数据挖掘就是最重要的两部分 在前几期的科普中 小编已经为大家介绍了大数据分析的相关情况 本期小编就为大家讲解大数据挖掘技术 让大家轻轻松松弄懂什么是大数据挖掘技术 什
  • 01 Datafountain_云状识别_top1

    01 Datafountain 云状识别 top1 摘要 1 云状识别算法总体思路和架构 2 云状识别算法具体实现过程 2 1 图像增强 2 2 多图像尺寸训练 2 3 选用densenet161预训练模型进行fine tune 2 4 差
  • Kotlin-Retrofit2和Rxjava2的网络封装,展示Github的用户信息

    目录 开始 1 先添加依赖 2 封装请求类 3 RESTful API请求响应的处理 4 线程与生命周期 5 使用 效果如下 开始 1 先添加依赖 Retrofit相关 implementation com squareup okhttp3