Kotlin高效地开发Android App(一)

2020-04-1911:10:55APP与小程序开发Comments1,609 views字数 4544阅读模式

做区块链相关的钱包项目,新的App使用全新的技术栈。在Android中我们使用Kotlin+RxJava+Android Architecture Components,在iOS中使用Swift+RxSwift。本文不讨论App的架构,只讨论项目中所使用到的Kotlin的特性。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

在Android的App中,可以毫不夸张地说,我们95%以上的代码使用了Kotlin开发的。由此,很有必要对这一阶段使用Kotlin做一个简单的小结。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

使用的Kotlin特性:

一.扩展函数

Kotlin允许开发者在不改变已有类的情况下,为某个类添加新的函数。这个特性叫做扩展函数。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

举一个简单的例子。如果要关闭一个I/O流,使用Java可能是写一个工具方法。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

    /**
     * 安全关闭io流
     * @param closeable
     */
    public static void closeQuietly(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
复制代码

对Kotlin而言,可以对Closeable扩展一个函数closeQuietly()。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

fun Closeable?.closeQuietly() {
    try {
        this?.close()
    } catch (e: Throwable) {
    }
}
复制代码

之后,任何实现了Closeable接口的类,都可以使用它本身的closeQuietly()方法来关闭流。我们不再需要那个工具方法了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

在项目中,我们使用扩展函数对Glide做了封装,大大简化了Glide的使用。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

/**
 * 占位符矩形
 */
fun ImageView.load(url: String) {
    get(url).placeholder(R.drawable.shape_default_rec_bg)
            .error(R.drawable.shape_default_rec_bg)
            .into(this)
}

/**
 * 占位符圆角矩形
 */
fun ImageView.loadRound(url: String) {
    get(url).placeholder(R.drawable.shape_default_round_bg)
            .error(R.drawable.shape_default_round_bg)
//            .apply(RequestOptions.bitmapTransform(RoundedCornersTransformation(DisplayUtil.dp2px(context, 6f), 0)))
            .transform(RoundedCornersTransformation(DisplayUtil.dp2px(context, 6f), 0))
            .into(this)
}

/**
 * 占位符圆形
 */
fun ImageView.loadCircle(url: Drawable) {
    get(url).placeholder(R.drawable.shape_default_circle_bg)
            .error(R.drawable.shape_default_circle_bg)
            .into(this)
}

fun ImageView.loadCircle(url: String) {
    get(url).placeholder(R.drawable.shape_default_circle_bg)
            .error(R.drawable.shape_default_circle_bg)
            .into(this)
}

fun ImageView.get(url: String): GlideRequest<Drawable> = GlideApp.with(context).load(url)
fun ImageView.get(url: Drawable): GlideRequest<Drawable> = GlideApp.with(context).load(url)
复制代码

除此之外,我们还很多地方都用到了扩展函数。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

我顺便更新了我的Kolin的工具类库,它包括各种utils和各种extension https://github.com/fengzhizi715/SAF-Kotlin-Utils文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

二.尾随闭包

一开始我并不了解这个概念。偶然间我看到我们的小伙伴在使用RxBus时,写下了这样的代码:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

RxBus.get().register(LogoutEvent::class.java) { refresh() }
复制代码

当时我感觉很疑惑,因为RxBus是我写的,记得没有提供这样的方法啊。点击register()方法进去看之后,发现register是这样的:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

    public <T> Disposable register(Class<T> eventType, Consumer<T> onNext) {
        return toObservable(eventType).observeOn(AndroidSchedulers.mainThread()).subscribe(onNext);
    }
复制代码

由于使用了Kotlin,该register方法的使用可以简化成这样:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

RxBus.get().register(LogoutEvent::class.java,{
            refresh()
        })
复制代码

由于register()最后一个参数是一个方法或者说是一个闭包,可以把方法或者闭包提到最外面。变成项目中看到的样子:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

RxBus.get().register(LogoutEvent::class.java) { refresh() }
复制代码

这就是尾随闭包,可以让代码看起来更加简洁。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

三.with的用法

with是将某个对象作为函数的参数,在函数块内可以通过 this 指代该对象。在函数块内可以直接调用对象的方法或者属性。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

/**
 * Calls the specified function [block] with the given [receiver] as its receiver and returns its result.
 */
@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return receiver.block()
}
复制代码

在使用with之前的某个Adapter文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

class AppPublisherAdapter : BaseAdapter<BoundAppInfoResponse.AppInfo>() {

    override fun getLayoutId(viewType: Int): Int = R.layout.cell_app_publisher

    override fun onBindViewHolderImpl(holder: BaseViewHolder, position: Int,content: BoundAppInfoResponse.AppInfo) {
        holder.itemView.tv_game_name.text = content.name

        if (content.is_bound) {
            holder.itemView.tv_bound_user_name.text = content.bound_user_name
            holder.itemView.tv_bound_user_name.setTextColor(context.resources.getColor(R.color.color_bound_user_name))
        } else {
            holder.itemView.tv_bound_user_name.text = context.getString(R.string.bind_on_account)
            holder.itemView.tv_bound_user_name.setTextColor(context.resources.getColor(R.color.color_bind_on_account))
        }
        holder.itemView.iv_game_icon.load(content.logo_url)
    }
}
复制代码

使用with之后,该函数块可以省略"content."文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

class AppPublisherAdapter : BaseAdapter<BoundAppInfoResponse.AppInfo>() {

    override fun getLayoutId(viewType: Int): Int = R.layout.cell_app_publisher

    override fun onBindViewHolderImpl(holder: BaseViewHolder, position: Int, content: BoundAppInfoResponse.AppInfo) {

        with(content) {
            holder.itemView.tv_game_name.text = name

            if (is_bound) {
                holder.itemView.tv_bound_user_name.text = bound_user_name
                holder.itemView.tv_bound_user_name.setTextColor(context.color(R.color.color_bound_user_name))
            } else {
                holder.itemView.tv_bound_user_name.text = context.string(R.string.bind_on_account)
                holder.itemView.tv_bound_user_name.setTextColor(context.color(R.color.color_bind_on_account))
            }
            holder.itemView.iv_game_icon.load(logo_url)
        }
    }
}
复制代码

四.其他

这部分的内容并不是Kotlin的特性,是我使用Kotlin开发的工具。比如日志框架L以及Retrofit的日志拦截器。这些库,其实很早就开发了,最近稍微升级了一下功能。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

L的github地址: https://github.com/fengzhizi715/SAF-Kotlin-log文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

Retrofit日志拦截器的github地址: https://github.com/fengzhizi715/saf-logginginterceptor文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

日志拦截器的效果图:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

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

总结

Kotlin吸收了多种语言的优点,相对于Java有很多激动人心的特性,极大地提高了开发效率。本文介绍的特性也只是沧海一粟。接下来,我会整理更多项目中所使用的Kotlin特性。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

作者:Tony沈哲
链接:https://juejin.im/post/5ade9ce3f265da0b80705e22
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html

文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18196.html
  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/xcx/18196.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定