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的更多相关文章
- Android网络请求框架之Retrofit实践
网络访问框架经过了从使用最原始的AsyncTask构建简单的网络访问框架(甚至不能称为框架),后来使用开源的android-async-http库,再到使用google发布的volley库,一直不懈的 ...
- 【我的Android进阶之旅】Realm数据库学习资料汇总(持续更新)
介绍 realm是一个跨平台移动数据库引擎,支持iOS.OS X(Objective-C和Swift)以及Android. 2014年7月发布.由YCombinator孵化的创业团队历时几年打造,是第 ...
- MVP实战心得—封装Retrofit2.0+RxAndroid+RxBus
响应式编程框架,rxjava的扩展,很爽的链式编程 魅力在于对数据的处理,与线程切换的灵活性. 用来处理异步操作(Lambda表达式不会用.用Lambda表达式代码会更少,但不会的人会看不懂代码.不是 ...
- 我的Android进阶之旅------>RxJava学习资料汇总
在响应式编程中,应该牢记以下两点: everything is a stream(一切皆流) don't break the chain(不要打断链式结构) 记住,可观测序列就像一条河,它们是流动的. ...
- 不可错过的几款GitHub开源项目
工作之余或者周末感觉无聊?不知道干什么?想继续提高技术,但是不知道做什么的同学,看过来,不妨利用闲暇时间来撸几个 GitHub 上还不错的开源项目,本文推荐的开源项目比较适合新手.及对MVP设计模式不 ...
- 【转】Android开发规范
转自:https://github.com/Blankj/AndroidStandardDevelop 摘要 1 前言 2 AS 规范 3 命名规范 4 代码样式规范 5 资源文件规范 6 版本统一规 ...
- 【转】Android 开发规范(完结版)
摘要 1 前言 2 AS 规范 3 命名规范 4 代码样式规范 5 资源文件规范 6 版本统一规范 7 第三方库规范 8 注释规范 9 测试规范 10 其他的一些规范 1 前言 为了有利于项目维护.增 ...
- Android 你应该注意的开发规范
本文由Blankj投稿. Blankjd的博客地址: http://www.jianshu.com/u/46702d5c6978 为了利于项目维护以及规范开发,促进成员之间Code Review的效率 ...
- android -------- Retrofit + RxJava2.0 + Kotlin + MVP 开发的 WanAndroid 项目
简介 wanandroid项目基于 Retrofit + RxJava2.0 + Kotlin + MVP 用到的依赖 implementation 'io.reactivex.rxjava2:rxj ...
随机推荐
- Windows Server2012R2 添加Microsoft .NET Framework 3.5 功能失败的解决方法
最近部署了一台Windows Server2012R2的虚机,在安装sharepoint foundation 2013之前安装必备的组件的时候安装到一半报错了没有安装成功,后来发现原来是系统的.NE ...
- C++ Primer 有感(多重继承与虚继承)
1.多重继承的构造次序:基类构造函数按照基类构造函数在类派生列表中的出现次序调用,构造函数调用次序既不受构造函数初始化列表中出现的基类的影响,也不受基类在构造函数初始化列表中的出现次序的影响.2.在单 ...
- PA 项目创建任务
---- 创建任务 DECLARE p_project_id NUMBER := 155233; p_task_number VARCHAR2(240) := 'CXYTEST0001'; p_tas ...
- 【python】网页中字符编码转换 unicode-escape
有的时候我们用python来抓取网页会得到类似 '\\u003C\\u0066\\u0072\\u006F\\u006D\\u003E' 或者 '%u003c%u0062%u0072%u003e%u0 ...
- clisp, scheme 和 clojure 初学习
clisp, scheme和clojure 初学习 1 clojure "clojure绝对会成为你的编程工具箱里的终极武器" "其他语言可能只是工具,但 Clojure ...
- EBS 外部信用风险检查
DECLARE l_msg_count NUMBER; l_msg_data VARCHAR2(2000); l_return_status VARCHAR2(30); l_cc_hold_comme ...
- 三层登录实例VB.NET版详解---理论加实战篇
层,百度百科这样解释,首先-重叠起来的东西:重叠起来的东西中的一部分:层次|表层|大气层.其次-重叠:重复:层峦叠嶂|层出不穷.最后-量词,用于可以分出层次的事物,女孩儿强烈的第六感,三层中的层一定是 ...
- android 加载图片oom若干方案小结
本文根据网上提供的一些技术方案加上自己实际开发中遇到的情况小结. 众所周知,每个Android应用程序在运行时都有一定的内存限制,限制大小一般为16MB或24MB(视手机而定).一般我们可以通过获取当 ...
- 【翻译】Ext JS最新技巧——2014-8-13
原文:Top Support Tips Greg Barry:新的框架. 新的文档类型(Doctype) 在Ext JS 5,只支持IE8+,因此不再古力用户使用严格的HTML文档类型.现在,推荐使用 ...
- 使用Visual Studio创建图片精灵(Image Sprite)——Web Essential
原文:Creating Image Sprite in Visual Studio - Web Essential 译者注:有关图片精灵的信息请参阅http://baike.baidu.com/vie ...