https://jqs7.com/kotlin-retrofit-rxandroid-realm/

原作者:Ahmed Rizwan

原文链接:Kotlin : Retrofit + RxAndroid + Realm

译文作者:Jqs7

审阅:@SusuwANjr

在这篇文章里面我会使用一些库(就我平时用那些),比如使用 Kotlin 和 Rx 来写 Retrofit 和 Realm 。

如果你是个 Retrofit 新手……建议你阅读一下这篇文章——保证亮瞎你狗眼让你眼前一亮!如果你不知道 Rx & Kotlin —— 看这里!

那我们开始吧:Kotlin + Rx + Retrofit + Realm 如果你像我一样,那一定很讨厌一大片的冗余的代码 咳咳 Java6 。自我开始从事安卓开发以来,经常遇到一些“什么鬼?!”的问题。

在语言上我觉得 Kotlin 大法就是好!像 Retrofit ,Realm 以及 RxAndroid 这些库真心省了不少代码。

蜀黍给你讲个可怕的故事:有次我负责一个项目,里面有 12 个 POJO 类,还有 12 个数据库表类(ORM),还有 12 个数据库模型映射类。如果你数学学得好的话,你就会发现……特喵的有 36 个类!还不只是这样,如果要改一个类,那就意味着 3 个类全都得改。

我当时就这表情…

如果我们不用 ORM 的话,我们还得去写模型到数据库的映射类,真特么得吓尿我!

所以解决办法是啥?对我来说就是 Realm + Retrofit 啦 (^o^)ノ 我还用了 RxAndroid ,因为有了 Rx 生活更美好,当然还有 Kotlin ,因为……

Kotlin 大法好!Kotlin 千秋万代,一统江湖!

把这些东西结合起来,那 36 个类所做的事情只要 12 个类就能完成了 (本来就应该这样嘛 (ゝ∀・))。不光这样,代码也会因为 Kotlin 而变得更加简洁,表达性更为良好!

小例子:从 Github API 获取数据

一个常见的应用场景:从 API 获取数据,把数据存储到数据库并显示出来。

完成品就像下图这样,只是一个很简单的例子……希望可以覆盖到基本的姿势点!

下面就讲讲该怎么把这个 app 给撸出来……

创建项目并启用 Kotlin

创建完项目我们做的第一件事就是启用 Kotlin ——首先要在 Android Studio 里面装好 Kotlin 插件。

我创建了一个只有一个 MainActivity 的空项目——直接打开 build.gradle 文件,然后打开 action 列表(快捷键 ctrl+shift+a)

吼的!我们现在可以用 Kotlin 来写代码了!

现在的 MainActivity,标准格式,木有惊喜

我们可以像下面这样把 java 代码转成 Kotlin

现在 MainActivity 变成了下面这样……

Holy mother of Kotlin!

添加 Rx — Retrofit — Realm 依赖

    //Realm
compile 'io.realm:realm-android:0.87.4'
//RxAndroid
compile 'io.reactivex:rxandroid:1.1.0'
compile 'io.reactivex:rxjava:1.1.0'
//RxBindings
compile 'com.jakewharton.rxbinding:rxbinding:0.3.0'
//Retrofit
compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'
//Retrofit Adapter and Converter
compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2'
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
//Glide
compile 'com.github.bumptech.glide:glide:3.7.0'
//Databinding and Realm Annotations
kapt 'com.android.databinding:compiler:1.0-rc4'
kapt "io.realm:realm-annotations:0.87.4"
kapt "io.realm:realm-annotations-processor:0.87.4"

我还使用了 Databinding !因为用 Databinding 的人比较帅 (ゝ∀・)

你大概想问: kapt 是什么鬼?好吧,它是Kotlin内置的注解处理器。

把这个添加到 build.gradle

在这个项目里面我还得把 kapt 的 generateStubs 给打开,因为要用它来生成代码。

万事俱备!开始写代码啦!

Model

我们使用的 API 地址是:

https://api.github.com/users/ahmedrizwan

服务端返回的内容如下:

    {
"login": "ahmedrizwan",
"id": 4357275,
"avatar_url": "https://avatars.githubusercontent.com/u/4357275?v=3",
"gravatar_id": "",
"url": "https://api.github.com/users/ahmedrizwan",
"html_url": "https://github.com/ahmedrizwan",
"followers_url": "https://api.github.com/users/ahmedrizwan/followers",
"following_url": "https://api.github.com/users/ahmedrizwan/following{/other_user}",
"gists_url": "https://api.github.com/users/ahmedrizwan/gists{/gist_id}",
"starred_url": "https://api.github.com/users/ahmedrizwan/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/ahmedrizwan/subscriptions",
"organizations_url": "https://api.github.com/users/ahmedrizwan/orgs",
"repos_url": "https://api.github.com/users/ahmedrizwan/repos",
"events_url": "https://api.github.com/users/ahmedrizwan/events{/privacy}",
"received_events_url": "https://api.github.com/users/ahmedrizwan/received_events",
"type": "User",
"site_admin": false,
"name": "ahmed",
"company": null,
"blog": null,
"location": "Rawalpindi, Pakistan",
"email": null,
"hireable": null,
"bio": null,
"public_repos": 9,
"public_gists": 0,
"followers": 5,
"following": 9,
"created_at": "2013-05-06T18:32:59Z",
"updated_at": "2015-08-29T18:17:58Z"
}

在这个例子里面,只要把 id, name, avatarurl 和 publicrepos 从返回信息里面提取出来就够了。所以 model 类就像下面这样(同时也是个 realm 类):

    @RealmClass
open class Github : RealmObject() { @PrimaryKey
@SerializedName("id")
@Expose
open var id: Int = 0 @SerializedName("avatar_url")
@Expose
open var avatarUrl: String? = null @SerializedName("name")
@Expose
open var name: String? = null @SerializedName("public_repos")
@Expose
open var publicRepos: Int? = null }

小提示:如果你需要JSON返回的所以属性的话,我建议你使用这个网站来生成一个 POJO 类,再像上面说的那样把 Java 代码转成 Kotlin 代码。

我们就用 RealmClass 注解说起吧,在 Kotlin 中需要为 Realm model 类加上这个注解,Realm 才能生成 Realm 代理类,PrimaryKey 也是一个 Realm 注解,表示主键属性(废话),剩下的就是 Gson 注解了……

open关键字正好跟 Java 里面的 final 相反。默认情况下,Kotlin 的类就是 final 的,如果你如果要一个类可以被继承,就必须把它声明为 open。这对于属性也是一样的,比如上面的 model 类里面,name 这个属性,它拥有一个 getter 和 setter,为了使它们可以被重写(因为 Realm 需要),我们就得在属性的前面加上 open 关键字。

Retrofit 接口

因为我们的端点地址是:

https://api.github.com/users/[some_user]

所以接口写出来就是下面这样:

interface GithubService {
@GET("users/{username}")
fun getGithubUser(@Path("username") username: String): Observable<Github>
}

上面我们直接返回了一个 Observable 的 Github,因为 Retrofit 集成了 Rx,简直就是碉堡了!

Retrofit Builder

val gson = GsonBuilder().setExclusionStrategies(object : ExclusionStrategy {
override fun shouldSkipField(f: FieldAttributes): Boolean {
return f.declaringClass == RealmObject::class.java
} override fun shouldSkipClass(clazz: Class<*>): Boolean {
return false
}
}).create() val retrofit: Retrofit = Retrofit.Builder()
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.baseUrl("https://api.github.com/")
.build() val githubService: GithubService = retrofit.create(
GithubService::class.java)

因为用了 Realm ,所以我们得重新声明一个 Gson 实例,添加排除策略(exclusion strategy)来跳过Realm生成的属性,不然 Gson 对于这个 model 就没什么卯月了。

在下面就是一个加入 RxJavaCallAdapter 工厂类启用 Rx 集成的 Retrofit 实例,我们还加了一个使用了上面创建的 Gson 实例的 Gson 解析器。

Rx 魔法

  githubService.getGithubUser("ahmedrizwan")
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ user ->
realm.beginTransaction()
realm.copyToRealmOrUpdate(user)
realm.commitTransaction()
updateViews(binding, user)
},
{ error ->
Log.e("Error", error.message)
}
)

现在我们所做的就是:获取 observable 对象,订阅之,并获取 Github 对象。只有一获取到 Github 对象,就可以很简单的把用户保存到 Realm 数据库里面了。

缓存

缓存也是可以有的 (=゚ω゚)=,我们可以一开始就可以获取 Realm 数据库里面的数据(如果存在的话),就像下面这样:

    val realm = Realm.getDefaultInstance()

    //get user if it's already saved
val savedUser: Github? = RealmQuery.createQuery(realm,
Github::class.java).findFirst()
updateViews(binding, savedUser)

到这里就已经差不多完成了,接下来就差运行…

鼓个掌

你可以在这里找到这个例子的所有代码,希望这篇文章对你有所帮助。

Happy coding!

Kotlin : Retrofit + RxAndroid + Realm的更多相关文章

  1. Android网络请求框架之Retrofit实践

    网络访问框架经过了从使用最原始的AsyncTask构建简单的网络访问框架(甚至不能称为框架),后来使用开源的android-async-http库,再到使用google发布的volley库,一直不懈的 ...

  2. 【我的Android进阶之旅】Realm数据库学习资料汇总(持续更新)

    介绍 realm是一个跨平台移动数据库引擎,支持iOS.OS X(Objective-C和Swift)以及Android. 2014年7月发布.由YCombinator孵化的创业团队历时几年打造,是第 ...

  3. MVP实战心得—封装Retrofit2.0+RxAndroid+RxBus

    响应式编程框架,rxjava的扩展,很爽的链式编程 魅力在于对数据的处理,与线程切换的灵活性. 用来处理异步操作(Lambda表达式不会用.用Lambda表达式代码会更少,但不会的人会看不懂代码.不是 ...

  4. 我的Android进阶之旅------>RxJava学习资料汇总

    在响应式编程中,应该牢记以下两点: everything is a stream(一切皆流) don't break the chain(不要打断链式结构) 记住,可观测序列就像一条河,它们是流动的. ...

  5. 不可错过的几款GitHub开源项目

    工作之余或者周末感觉无聊?不知道干什么?想继续提高技术,但是不知道做什么的同学,看过来,不妨利用闲暇时间来撸几个 GitHub 上还不错的开源项目,本文推荐的开源项目比较适合新手.及对MVP设计模式不 ...

  6. 【转】Android开发规范

    转自:https://github.com/Blankj/AndroidStandardDevelop 摘要 1 前言 2 AS 规范 3 命名规范 4 代码样式规范 5 资源文件规范 6 版本统一规 ...

  7. 【转】Android 开发规范(完结版)

    摘要 1 前言 2 AS 规范 3 命名规范 4 代码样式规范 5 资源文件规范 6 版本统一规范 7 第三方库规范 8 注释规范 9 测试规范 10 其他的一些规范 1 前言 为了有利于项目维护.增 ...

  8. Android 你应该注意的开发规范

    本文由Blankj投稿. Blankjd的博客地址: http://www.jianshu.com/u/46702d5c6978 为了利于项目维护以及规范开发,促进成员之间Code Review的效率 ...

  9. android -------- Retrofit + RxJava2.0 + Kotlin + MVP 开发的 WanAndroid 项目

    简介 wanandroid项目基于 Retrofit + RxJava2.0 + Kotlin + MVP 用到的依赖 implementation 'io.reactivex.rxjava2:rxj ...

随机推荐

  1. 精通CSS+DIV网页样式与布局--页面和浏览器元素

    在页面和浏览器中,除了文字.图片.表格.表单等,还有很多各种各样的元素,在上篇博文中,小编主要简单的介绍了一下在CSS中如何设置表格和表单,今天小编主要简单介绍一下丰富的超链接特效.鼠标特效.页面滚动 ...

  2. Linux服务器Jboss运行环境搭建步骤和开机自动启动脚本编写运行

    Jboss运行环境:Linux+Jdk+Jboss+jsp系统 Jboss软件说明:类似于Tomcat,就是一个跑Jsp系统的环境,他的站点路径跟Tomcat类似,Tomcat存放站点文件到webap ...

  3. go: 一个通用log模块的实现

    在go里面,虽然有log模块,但是该模块提供的功能并不强,譬如就没有我们常用的level log功能,但是自己实现一个log模块也并不困难. 对于log的level,我们定义如下: const ( L ...

  4. 青年菜君与小农女送菜商业模式PK

    青年菜君与小农女送菜商业模式PK   对比项 青年菜君 小农女送菜 优势 劣势 开业 2014年3月3日 2013年9月 渠道 地铁捕获用户 写字楼配送 送货 来店面自取 送货到写字楼 菜君 1.减少 ...

  5. Dynamics crm2013 IFD部署后启用多组织

    对CRM的多组织都不会陌生,在常规模式下新建组织后更改下url后面的组织名称即可访问新的组织了,而在部署IFD后就需要注意两点:1.域名的DNS解析:2.relying patry trust的更新 ...

  6. Touch Handling in Cocos2D 3.x(七)

    在touchMoved方法中寻找触摸在父节点(CCScene)中的位置并且移动CCDragSprite到其父节点的相应位置中去. 在我们在动作中观赏拖放机制之前,我们需要使用这个新实现的类.打开Mai ...

  7. Java应用服务器Resin

    Resin是CAUCHO公司(http://www.caucho.com/)的产品,是一个非常流行的支持servlets 和jsp的引擎,速度非常快.Resin本身包含了一个支持HTTP/1.1的WE ...

  8. Linux学习笔记 --iptables防火墙配置

    iptables防火墙配置 一.防火墙简介 1.功能: 1)通过源端口,源IP地址,源MAC地址,包中特定标记和目标端口,IP,MAC来确定数据包是否可以通过防火墙 2)分割内网和外网[附带的路由器的 ...

  9. JSONP获取Twitter和Facebook文章数

    原文链接: Retrieve Twitter and Facebook Counts with JSON 翻译人员: 铁锚 原文日期: 2014年02月19日 翻译日期: 2014年02月22日 !! ...

  10. 线性表的顺序存储设计和实现 - API函数实现

    基本概念 设计与实现 插入元素算法 判断线性表是否合法 判断插入位置是否合法 把最后一个元素到插入位置的元素后移一个位置 将新元素插入 线性表长度加1 获取元素操作 判断线性表是否合法 判断位置是否合 ...