JSON : Placeholder

JSON : Placeholder (https://jsonplaceholder.typicode.com/) 是一个用于测试的 REST API 网站。

以下使用 RxJava2 + Retrofit2 调用该网站的 REST API,获取字符串以及 JSON 数据。

  • GET /posts/1
  • GET /posts
  • POST /posts
  • PUT /posts/1
  • DELETE /posts/1

所有 GET API 都返回JSON数据,格式(JSON-Schema)如下:

  1. {
  2. "type":"object",
  3. "properties": {
  4. "userId": {"type" : "integer"},
  5. "id": {"type" : "integer"},
  6. "title": {"type" : "string"},
  7. "body": {"type" : "string"}
  8. }
  9. }

创建工程

打开 Intellij IDEA,File / New / Project...

在 New Project 向导的第1页,选 Gradle,Project SDK 选 1.8,Additional Libraries and Frameworks 选 Java + Kotlin(Java)。

在向导的第2页填上 ArtifactId

在向导的第3页选中 use auto-import

在向导的第4页点击 Finish 按钮创建工程

build.gradle 内容如下

  1. plugins {
  2. id 'java'
  3. id 'org.jetbrains.kotlin.jvm' version '1.2.60'
  4. }
  5. version '1.0-SNAPSHOT'
  6. sourceCompatibility = 1.8
  7. repositories {
  8. mavenCentral()
  9. }
  10. dependencies {
  11. compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
  12. testCompile group: 'junit', name: 'junit', version: '4.12'
  13. }
  14. compileKotlin {
  15. kotlinOptions.jvmTarget = "1.8"
  16. }
  17. compileTestKotlin {
  18. kotlinOptions.jvmTarget = "1.8"
  19. }

将 dependencies 这部分的内容改为:

  1. def retrofit_version = '2.4.0'
  2. dependencies {
  3. implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
  4. testImplementation group: 'junit', name: 'junit', version: '4.12'
  5. implementation 'io.reactivex.rxjava2:rxjava:2.1.16'
  6. implementation 'io.reactivex.rxjava2:rxkotlin:2.2.0'
  7. implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
  8. implementation "com.squareup.retrofit2:adapter-rxjava2:$retrofit_version"
  9. implementation "com.squareup.retrofit2:converter-gson:$retrofit_version"
  10. implementation "com.squareup.retrofit2:converter-scalars:$retrofit_version"
  11. }

这一段一共引用了 RxJava, RxKotlin, Retrofit 3个库。

其中 Retrofit 这个库中还包含了 RxJava 的适配器,以及 Gson 和字符串的转换器。

Post 对象

jsonschema2pojo 可以将 JSON 数据或格式自动转换为 Java 的 POJO 类。

  1. data class Post(val userId: Int, val id: Int, val title: String, val body: String) {
  2. override fun toString() =
  3. "Post {userId = $userId, id = $id, title = \"$title\", body = \"${body.replace("\n", "\\n")}\"}"
  4. }

Post 对象负责 Kotlin 对象与 JSON 数据之间的相互转换。

由于两者字段名相同,这里不需要使用注解。

  1. // 如果需要加上注解的话
  2. data class Post(@SerializedName("userId") @Expose val userId: Int,
  3. @SerializedName("id") @Expose val id: Int,
  4. @SerializedName("title") @Expose val title: String,
  5. @SerializedName("body") @Expose val body: String) {
  6. // ...
  7. }

Retrofit 接口

  1. interface RestPost {
  2. @GET
  3. fun getPostAsString(@Url url: String): Observable<String>
  4. @GET("posts/{id}")
  5. fun getPostAsJson(@Path("id") id: Int): Observable<Post>
  6. @GET("posts")
  7. fun getPosts(): Observable<List<Post>>
  8. @FormUrlEncoded
  9. @POST("posts")
  10. fun createPost(@Field("userId") userId: Int,
  11. @Field("title") title: String,
  12. @Field("body") body: String): Observable<Post>
  13. @FormUrlEncoded
  14. @PUT("posts/{id}")
  15. fun updatePost(@Field("userId") userId: Int,
  16. @Path("id") id: Int,
  17. @Field("title") title: String,
  18. @Field("body") body: String): Observable<Post>
  19. @DELETE("posts/{id}")
  20. fun deletePost(@Path("id") id: Int): Observable<String>
  21. }

Retrofit 库使用专用接口调用 REST API。

  • 接口中的每一个方法都对应于一种 API 调用。
  • 注解 @GET @POST @PUT @DELETE 表示 API 调用时所使用的 HTTP 方法。
  • 注解 @GET 中带的值表示 API 调用时所包含的相对路径,其中可包含路径变量。

    "posts/{id}" 中的 {id} 为路径变量。
  • 注解 @Url 表示参数为路径。
  • 注解 @Path("id") 表示参数为路径变量。
  • 注解 @Field 表示参数为 HTTP 请求体中的键值对。
  • 使用注解 @Field 的方法必须加上注解 @FormUrlEncoded。

Retrofit 对象

  1. val retrofitJson: Retrofit = Retrofit.Builder()
  2. .baseUrl("https://jsonplaceholder.typicode.com/")
  3. .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
  4. .addConverterFactory(GsonConverterFactory.create())
  5. .build()
  6. val retrofitString: Retrofit = Retrofit.Builder()
  7. .baseUrl("https://jsonplaceholder.typicode.com/")
  8. .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
  9. .addConverterFactory(ScalarsConverterFactory.create())
  10. .build()
  • retrofitJson 对象用于处理 REST API 所返回的 JSON 数据。
  • retrofitString 对象用于处理 REST API 所返回的字符串数据。

调用 REST API

  1. fun getPostAsString(): Observable<String> =
  2. retrofitString.create(RestPost::class.java)
  3. .getPostAsString("posts/1")
  4. fun getPostAsJson(): Observable<Post> =
  5. retrofitJson.create(RestPost::class.java)
  6. .getPostAsJson(1)
  7. fun getPosts(n: Long): Observable<Post> =
  8. retrofitJson.create(RestPost::class.java)
  9. .getPosts().flatMapIterable { x -> x }.take(n)
  10. fun createPost(): Observable<Post> =
  11. retrofitJson.create(RestPost::class.java)
  12. .createPost(101, "test title", "test body")
  13. fun updatePost(): Observable<Post> =
  14. retrofitJson.create(RestPost::class.java)
  15. .updatePost(101, 1, "test title", "test body")
  16. fun deletePost(): Observable<String> =
  17. retrofitString.create(RestPost::class.java)
  18. .deletePost(1)
  • getPostAsString 函数取出第1个Post,返回字符串
  • getPostAsJson 函数取出第1个Post,返回Post对象
  • getPosts 函数取出前n个Post,返回n个Post对象
  • createPost 函数创建1个Post,返回所创建的Post对象
  • updatePost 函数更新第1个Post,返回所更新的Post对象
  • deletePost 函数删除第1个Post,返回字符串

main 函数

  1. fun main(args: Array<String>) {
  2. getPostAsString().subscribe(::println)
  3. getPostAsJson().subscribe(::println)
  4. getPosts(2).subscribe(::println)
  5. createPost().subscribe(::println)
  6. updatePost().subscribe(::println)
  7. deletePost().subscribe(::println)
  8. }

输出结果

  1. {
  2. "userId": 1,
  3. "id": 1,
  4. "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
  5. "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
  6. }
  7. Post {userId = 1, id = 1, title = "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", body = "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"}
  8. Post {userId = 1, id = 1, title = "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", body = "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"}
  9. Post {userId = 1, id = 2, title = "qui est esse", body = "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"}
  10. Post {userId = 101, id = 101, title = "test title", body = "test body"}
  11. Post {userId = 101, id = 1, title = "test title", body = "test body"}
  12. {}

ReactiveX 学习笔记(14)使用 RxJava2 + Retrofit2 调用 REST API的更多相关文章

  1. ReactiveX 学习笔记(0)学习资源

    ReactiveX 学习笔记 ReactiveX 学习笔记(1) ReactiveX 学习笔记(2)创建数据流 ReactiveX 学习笔记(3)转换数据流 ReactiveX 学习笔记(4)过滤数据 ...

  2. mybatis学习笔记(14)-查询缓存之中的一个级缓存

    mybatis学习笔记(14)-查询缓存之中的一个级缓存 标签: mybatis mybatis学习笔记14-查询缓存之中的一个级缓存 查询缓存 一级缓存 一级缓存工作原理 一级缓存測试 一级缓存应用 ...

  3. 并发编程学习笔记(14)----ThreadPoolExecutor(线程池)的使用及原理

    1. 概述 1.1 什么是线程池 与jdbc连接池类似,在创建线程池或销毁线程时,会消耗大量的系统资源,因此在java中提出了线程池的概念,预先创建好固定数量的线程,当有任务需要线程去执行时,不用再去 ...

  4. 【转】 C#学习笔记14——Trace、Debug和TraceSource的使用以及日志设计

    [转] C#学习笔记14——Trace.Debug和TraceSource的使用以及日志设计 Trace.Debug和TraceSource的使用以及日志设计   .NET Framework 命名空 ...

  5. [C++学习笔记14]动态创建对象(定义静态方法实现在map查找具体类名对应的创建函数,并返回函数指针,map真是一个万能类)good

    [C++学习笔记14]动态创建对象   C#/Java中的反射机制 动态获取类型信息(方法与属性) 动态创建对象 动态调用对象的方法 动态操作对象的属性 前提:需要给每个类添加元数据 动态创建对象 实 ...

  6. Ext.Net学习笔记14:Ext.Net GridPanel Grouping用法

    Ext.Net学习笔记14:Ext.Net GridPanel Grouping用法 Ext.Net GridPanel可以进行Group操作,例如: 如何启用Grouping功能呢?只需要在Grid ...

  7. Memcached 学习笔记(二)——ruby调用

    Memcached 学习笔记(二)——ruby调用 上一节我们讲述了怎样安装memcached及memcached常用命令.这一节我们将通过ruby来调用memcached相关操作. 第一步,安装ru ...

  8. SQL反模式学习笔记14 关于Null值的使用

    目标:辨别并使用Null值 反模式:将Null值作为普通的值,反之亦然 1.在表达式中使用Null: Null值与空字符串是不一样的,Null值参与任何的加.减.乘.除等其他运算,结果都是Null: ...

  9. golang学习笔记14 golang substring 截取字符串

    golang学习笔记14 golang substring 截取字符串golang 没有java那样的substring函数,但支持直接根据 index 截取字符串mystr := "hel ...

随机推荐

  1. [UE4]蓝图调试

    1.蓝图下断点:选择蓝图节点按F9下断点:再按一下F9就会去掉断点. 2.游戏运行到断点会自动这暂停,鼠标移到某个变量上面,会显示该变量的值. 3.按F10执行下一步. 4.蓝图调试没有跳出函数的功能 ...

  2. [UE4]背景模糊

    被遮挡的都会被模糊,没被遮挡的不会模糊

  3. Android拨打接听电话自动免提

    权限: <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-p ...

  4. python中文件操作

      打印进度条

  5. 知识点:MySQL表名不区分大小写的设置方法

    在用centox安装mysql后,把项目的数据库移植了过去,发现一些表的数据查不到,排查了一下问题,最后发现是表名的大小写不一致造成的. mysql在windows系统下安装好后,默认是对表名大小写不 ...

  6. switch case 变量初始化问题

    今天再写alsa的时候遇到一个稀奇古怪的问题,网上看了下资料,摘出来入下 代码: int main() { ; switch(a) { : ; break; : break; default: bre ...

  7. Java基础知识_毕向东_Java基础视频教程笔记(26 反射)

    Java反射机制: 是在运行状态中,对于任意一个类(class)文件,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性.这种动态获取的信息以及动态调用对象的方法的功 ...

  8. (转)开源OpenWRT知识

    原博地址:http://www.thinkingquest.net/article/466 我们都需要使用google提供的搜索,gmail等优质服务.但是由于方墙的存在,使得大家各自搞各自的FQ办法 ...

  9. CF603EPastoral Oddities

    /* LCT管子题(说的就是你 水管局长) 首先能得到一个结论, 那就是当且仅当所有联通块都是偶数时存在构造方案 LCT动态加边, 维护最小生成联通块, 用set维护可以删除的边, 假如现在删除后不影 ...

  10. Web Service进阶

    选框架犹如选媳妇,选来选去,最后我还是选了“丑媳妇(CXF)”,为什么是它?因为 CXF 是 Apache 旗下的一款非常优秀的 WS 开源框架,具备轻量级的特性,而且能无缝整合到 Spring 中. ...