使用Kotlin高效地開發(fā)Android App(一)

星戰(zhàn)小兵.jpg

背景

最近我們在做區(qū)塊鏈相關(guān)的錢包項(xiàng)目,新的App使用全新的技術(shù)棧。在Android中我們使用Kotlin+RxJava+Android Architecture Components,在iOS中使用Swift+RxSwift。本文不討論App的架構(gòu),只討論項(xiàng)目中所使用到的Kotlin的特性。

在Android的App中,可以毫不夸張地說,我們95%以上的代碼使用了Kotlin開發(fā)的。由此,很有必要對這一階段使用Kotlin做一個簡單的小結(jié)。

使用的Kotlin特性:

一.擴(kuò)展函數(shù)

Kotlin允許開發(fā)者在不改變已有類的情況下,為某個類添加新的函數(shù)。這個特性叫做擴(kuò)展函數(shù)。

舉一個簡單的例子。如果要關(guān)閉一個I/O流,使用Java可能是寫一個工具方法。

    /**
     * 安全關(guān)閉io流
     * @param closeable
     */
    public static void closeQuietly(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

對Kotlin而言,可以對Closeable擴(kuò)展一個函數(shù)closeQuietly()。

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

之后,任何實(shí)現(xiàn)了Closeable接口的類,都可以使用它本身的closeQuietly()方法來關(guān)閉流。我們不再需要那個工具方法了。

在項(xiàng)目中,我們使用擴(kuò)展函數(shù)對Glide做了封裝,大大簡化了Glide的使用。

/**
 * 占位符矩形
 */
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)

除此之外,我們還很多地方都用到了擴(kuò)展函數(shù)。

我順便更新了我的Kolin的工具類庫,它包括各種utils和各種extension
https://github.com/fengzhizi715/SAF-Kotlin-Utils

二.尾隨閉包

一開始我并不了解這個概念。偶然間我看到我們的小伙伴在使用RxBus時(shí),寫下了這樣的代碼:

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

當(dāng)時(shí)我感覺很疑惑,因?yàn)镽xBus是我寫的,記得沒有提供這樣的方法啊。點(diǎn)擊register()方法進(jìn)去看之后,發(fā)現(xiàn)register是這樣的:

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

由于使用了Kotlin,該register方法的使用可以簡化成這樣:

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

由于register()最后一個參數(shù)是一個方法或者說是一個閉包,可以把方法或者閉包提到最外面。變成項(xiàng)目中看到的樣子:

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

這就是尾隨閉包,可以讓代碼看起來更加簡潔。

三.with的用法

with是將某個對象作為函數(shù)的參數(shù),在函數(shù)塊內(nèi)可以通過 this 指代該對象。在函數(shù)塊內(nèi)可以直接調(diào)用對象的方法或者屬性。

/**
 * 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

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之后,該函數(shù)塊可以省略"content."

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)
        }
    }
}

四.其他

這部分的內(nèi)容并不是Kotlin的特性,是我使用Kotlin開發(fā)的工具。比如日志框架L以及Retrofit的日志攔截器。這些庫,其實(shí)很早就開發(fā)了,最近稍微升級了一下功能。

L的github地址:
https://github.com/fengzhizi715/SAF-Kotlin-log

Retrofit日志攔截器的github地址:
https://github.com/fengzhizi715/saf-logginginterceptor

日志攔截器的效果圖:

request的效果圖.jpeg
response的效果圖.jpeg

總結(jié)

Kotlin吸收了多種語言的優(yōu)點(diǎn),相對于Java有很多激動人心的特性,極大地提高了開發(fā)效率。本文介紹的特性也只是滄海一粟。接下來,我會整理更多項(xiàng)目中所使用的Kotlin特性。

BTW,我在寫這篇文章的時(shí)候國內(nèi)第一個錢包版本剛剛做完,開始第一輪測試。

該系列的相關(guān)文章:
使用Kotlin高效地開發(fā)Android App(五)完結(jié)篇
使用Kotlin高效地開發(fā)Android App(四)
使用Kotlin高效地開發(fā)Android App(三)
使用Kotlin高效地開發(fā)Android App(二)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容