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

星戰(zhàn)小兵.jpg

背景

最近我們?cè)谧鰠^(qū)塊鏈相關(guān)的錢包項(xiàng)目淋叶,新的App使用全新的技術(shù)棧。在Android中我們使用Kotlin+RxJava+Android Architecture Components昙衅,在iOS中使用Swift+RxSwift。本文不討論App的架構(gòu)定鸟,只討論項(xiàng)目中所使用到的Kotlin的特性而涉。

在Android的App中,可以毫不夸張地說(shuō)联予,我們95%以上的代碼使用了Kotlin開發(fā)的啼县。由此,很有必要對(duì)這一階段使用Kotlin做一個(gè)簡(jiǎn)單的小結(jié)沸久。

使用的Kotlin特性:

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

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

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

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

對(duì)Kotlin而言挺峡,可以對(duì)Closeable擴(kuò)展一個(gè)函數(shù)closeQuietly()。

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

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

在項(xiàng)目中狭姨,我們使用擴(kuò)展函數(shù)對(duì)Glide做了封裝,大大簡(jiǎn)化了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的工具類庫(kù)暖眼,它包括各種utils和各種extension
https://github.com/fengzhizi715/SAF-Kotlin-Utils

二.尾隨閉包

一開始我并不了解這個(gè)概念惕耕。偶然間我看到我們的小伙伴在使用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方法的使用可以簡(jiǎn)化成這樣:

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

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

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

這就是尾隨閉包蛤铜,可以讓代碼看起來(lái)更加簡(jiǎn)潔。

三.with的用法

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

/**
 * 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之前的某個(gè)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的日志攔截器。這些庫(kù)氢伟,其實(shí)很早就開發(fā)了榜轿,最近稍微升級(jí)了一下功能。

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

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

日志攔截器的效果圖:

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

總結(jié)

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

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

該系列的相關(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)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末椅您,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子寡键,更是在濱河造成了極大的恐慌掀泳,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,331評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件西轩,死亡現(xiàn)場(chǎng)離奇詭異员舵,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)藕畔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,372評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門马僻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人注服,你說(shuō)我怎么就攤上這事韭邓。” “怎么了溶弟?”我有些...
    開封第一講書人閱讀 167,755評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵女淑,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我辜御,道長(zhǎng)鸭你,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,528評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮袱巨,結(jié)果婚禮上阁谆,老公的妹妹穿的比我還像新娘。我一直安慰自己瓣窄,他們只是感情好笛厦,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,526評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著俺夕,像睡著了一般裳凸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上劝贸,一...
    開封第一講書人閱讀 52,166評(píng)論 1 308
  • 那天姨谷,我揣著相機(jī)與錄音,去河邊找鬼映九。 笑死梦湘,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的件甥。 我是一名探鬼主播捌议,決...
    沈念sama閱讀 40,768評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼引有!你這毒婦竟也來(lái)了瓣颅?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,664評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤譬正,失蹤者是張志新(化名)和其女友劉穎宫补,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體曾我,經(jīng)...
    沈念sama閱讀 46,205評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡粉怕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,290評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了抒巢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贫贝。...
    茶點(diǎn)故事閱讀 40,435評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蛉谜,靈堂內(nèi)的尸體忽然破棺而出平酿,到底是詐尸還是另有隱情,我是刑警寧澤悦陋,帶...
    沈念sama閱讀 36,126評(píng)論 5 349
  • 正文 年R本政府宣布蜈彼,位于F島的核電站,受9級(jí)特大地震影響俺驶,放射性物質(zhì)發(fā)生泄漏幸逆。R本人自食惡果不足惜棍辕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,804評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望还绘。 院中可真熱鬧楚昭,春花似錦、人聲如沸拍顷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,276評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)昔案。三九已至尿贫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間踏揣,已是汗流浹背庆亡。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留捞稿,地道東北人又谋。 一個(gè)月前我還...
    沈念sama閱讀 48,818評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像娱局,于是被迫代替她去往敵國(guó)和親彰亥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子婶恼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,442評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容