|
|
51CTO旗下网站
|
|
移动端

使用Kotlin高效地开发Android App(一)

最近我们在做区块链相关的钱包项目,新的App使用全新的技术栈。在Android中我们使用Kotlin+RxJava+Android Architecture Components,在iOS中使用Swift+RxSwift。本文不讨论App的架构,只讨论项目中所使用到的Kotlin的特性。

作者:fengzhizi715来源:简书|2018-04-24 15:00

使用Kotlin高效地开发Android App(一)
星战小兵.jpg

背景

最近我们在做区块链相关的钱包项目,新的App使用全新的技术栈。在Android中我们使用Kotlin+RxJava+Android Architecture Components,在iOS中使用Swift+RxSwift。本文不讨论App的架构,只讨论项目中所使用到的Kotlin的特性。

在Android的App中,可以毫不夸张地说,我们95%以上的代码使用了Kotlin开发的。由此,很有必要对这一阶段使用Kotlin做一个简单的小结。

使用的Kotlin特性:

一.扩展函数

Kotlin允许开发者在不改变已有类的情况下,为某个类添加新的函数。这个特性叫做扩展函数。

举一个简单的例子。如果要关闭一个I/O流,使用Java可能是写一个工具方法。

  1. /**  
  2. * 安全关闭io流  
  3. * @param closeable  
  4. */  
  5. public static void closeQuietly(Closeable closeable) {  
  6. if (closeable != null) {  
  7. try { 
  8.  closeable.close();  
  9. } catch (IOException e) {  
  10. e.printStackTrace();  
  11.  
  12.  

对Kotlin而言,可以对Closeable扩展一个函数closeQuietly()。

  1. fun Closeable?.closeQuietly() {  
  2. try {  
  3. this?.close()  
  4. } catch (e: Throwable) {  
  5.  

之后,任何实现了Closeable接口的类,都可以使用它本身的closeQuietly()方法来关闭流。我们不再需要那个工具方法了。

在项目中,我们使用扩展函数对Glide做了封装,大大简化了Glide的使用。

  1. /**  
  2. * 占位符矩形  
  3. */  
  4. fun ImageView.load(url: String) {  
  5. get(url).placeholder(R.drawable.shape_default_rec_bg)  
  6. .error(R.drawable.shape_default_rec_bg) 
  7.  .into(this)  
  8.  
  9. /**  
  10. * 占位符圆角矩形  
  11. */  
  12. fun ImageView.loadRound(url: String) {  
  13. get(url).placeholder(R.drawable.shape_default_round_bg)  
  14. .error(R.drawable.shape_default_round_bg)  
  15. // .apply(RequestOptions.bitmapTransform(RoundedCornersTransformation(DisplayUtil.dp2px(context, 6f), 0))) 
  16.  .transform(RoundedCornersTransformation(DisplayUtil.dp2px(context, 6f), 0))  
  17. .into(this)  
  18.  /**  
  19. * 占位符圆形  
  20. */  
  21. fun ImageView.loadCircle(url: Drawable) {  
  22. get(url).placeholder(R.drawable.shape_default_circle_bg)  
  23. .error(R.drawable.shape_default_circle_bg)  
  24. .into(this)  
  25.  fun ImageView.loadCircle(url: String) {  
  26. get(url).placeholder(R.drawable.shape_default_circle_bg)  
  27. .error(R.drawable.shape_default_circle_bg)  
  28. .into(this)  
  29.  
  30. fun ImageView.get(url: String): GlideRequest = GlideApp.with(context).load(url)  
  31. fun ImageView.get(url: Drawable): GlideRequest = GlideApp.with(context).load(url) 

除此之外,我们还很多地方都用到了扩展函数。

我顺便更新了我的Kolin的工具类库,它包括各种utils和各种extension

https://github.com/fengzhizi715/SAF-Kotlin-Utils

二.尾随闭包

一开始我并不了解这个概念。偶然间我看到我们的小伙伴在使用RxBus时,写下了这样的代码:

  1. RxBus.get().register(LogoutEvent::class.java) { refresh() } 

当时我感觉很疑惑,因为RxBus是我写的,记得没有提供这样的方法啊。点击register()方法进去看之后,发现register是这样的:

  1. public Disposable register(Class eventType, Consumer onNext) {  
  2. return toObservable(eventType).observeOn(AndroidSchedulers.mainThread()).subscribe(onNext);  

由于使用了Kotlin,该register方法的使用可以简化成这样:

  1. RxBus.get().register(LogoutEvent::class.java,{  
  2. refresh()  
  3. }) 

由于register()最后一个参数是一个方法或者说是一个闭包,可以把方法或者闭包提到最外面。变成项目中看到的样子:

  1. RxBus.get().register(LogoutEvent::class.java) { refresh() } 

这就是尾随闭包,可以让代码看起来更加简洁。

三.with的用法

with是将某个对象作为函数的参数,在函数块内可以通过 this 指代该对象。在函数块内可以直接调用对象的方法或者属性。

  1. /**  
  2. * Calls the specified function [block] with the given [receiver] as its receiver and returns its result.  
  3. */  
  4. @kotlin.internal.InlineOnly  
  5. public inline fun with(receiver: T, block: T.() -> R): R {  
  6. contract {  
  7. callsInPlace(block, InvocationKind.EXACTLY_ONCE)  
  8.  
  9. return receiver.block()  

在使用with之前的某个Adapter

  1. class AppPublisherAdapter : BaseAdapter() {  
  2. override fun getLayoutId(viewType: Int): Int = R.layout.cell_app_publisher  
  3. override fun onBindViewHolderImpl(holder: BaseViewHolder, position: Int,content: BoundAppInfoResponse.AppInfo) {  
  4. holder.itemView.tv_game_name.text = content.name 
  5.  if (content.is_bound) {  
  6. holder.itemView.tv_bound_user_name.text = content.bound_user_name  
  7. holder.itemView.tv_bound_user_name.setTextColor(context.resources.getColor(R.color.color_bound_user_name))  
  8. else {  
  9. holder.itemView.tv_bound_user_name.text = context.getString(R.string.bind_on_account)  
  10. holder.itemView.tv_bound_user_name.setTextColor(context.resources.getColor(R.color.color_bind_on_account))  
  11.  
  12. holder.itemView.iv_game_icon.load(content.logo_url)  
  13.  

使用with之后,该函数块可以省略"content."

  1. class AppPublisherAdapter : BaseAdapter() {  
  2. override fun getLayoutId(viewType: Int): Int = R.layout.cell_app_publisher  
  3. override fun onBindViewHolderImpl(holder: BaseViewHolder, position: Int, content: BoundAppInfoResponse.AppInfo) {  
  4. with(content) {  
  5. holder.itemView.tv_game_name.text = name  
  6. if (is_bound) {  
  7. holder.itemView.tv_bound_user_name.text = bound_user_name  
  8. holder.itemView.tv_bound_user_name.setTextColor(context.color(R.color.color_bound_user_name))  
  9. else {  
  10. holder.itemView.tv_bound_user_name.text = context.string(R.string.bind_on_account)  
  11. holder.itemView.tv_bound_user_name.setTextColor(context.color(R.color.color_bind_on_account))  
  12.  
  13. holder.itemView.iv_game_icon.load(logo_url)  
  14.  
  15.  

四.其他

这部分的内容并不是Kotlin的特性,是我使用Kotlin开发的工具。比如日志框架L以及Retrofit的日志拦截器。这些库,其实很早就开发了,最近稍微升级了一下功能。

L的github地址:

  • https://github.com/fengzhizi715/SAF-Kotlin-log

Retrofit日志拦截器的github地址:

  • https://github.com/fengzhizi715/saf-logginginterceptor

日志拦截器的效果图:

使用Kotlin高效地开发Android App(一)
request的效果图.jpeg

使用Kotlin高效地开发Android App(一)
response的效果图.jpeg

总结

Kotlin吸收了多种语言的优点,相对于Java有很多激动人心的特性,极大地提高了开发效率。本文介绍的特性也只是沧海一粟。接下来,我会整理更多项目中所使用的Kotlin特性。

BTW,我在写这篇文章的时候国内第一个钱包版本刚刚做完,开始第一轮测试。

【编辑推荐】

  1. 用Kotlin优雅地开发Android应用
  2. 17位谷歌Android开发专家是如何看待Kotlin的?
  3. Kotlin将超越Java成为Android开发的第一语言?
  4. 来了,支持 iOS 开发的 Kotlin/Native v0.4 发布
  5. Google 推出让 Kotlin 代码更精简的 Android KTX
【责任编辑:未丽燕 TEL:(010)68476606】

点赞 0
分享:
大家都在看
猜你喜欢

读 书 +更多

非常网管——网络工程案例

本书面向企业网络应用需求,详细介绍了Windows网络互联解决方案、中小企业共享上网解决方案、基于ISA Server 2006的代理服务器与防火墙解决...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊