【思貨】kotlin協程優雅的與Retrofit纏綿-kotlin DSL簡述

這是一篇輔助文章,爲了輔助你們理解後面的文章,先前先簡單的闡述下kotlin的DSL。java

DSL是什麼

DSL指的是特定領域語言,利用kotlin的DSL語言,咱們能夠寫成更加整潔的代碼,是代碼的可閱讀行大幅度提高。基本的概念以及好處我就再也不重複闡述了,網上已經有不少相似的文章了,我就經過具體的代碼示例進行展現好了。bash

kotlin DSL代碼長什麼樣

EditText

我仍是從最多見EditTextTextWatcher提及。app

Java中當咱們須要添加文本輸入監聽的的時候,是以下的寫法:ide

editText.addTextChangedListener(new TextWatcher() {
	@Override
  public void beforeTextChanged(CharSequence s, int start, int count, int after) {

  }

  @Override
  public void onTextChanged(CharSequence s, int start, int before, int count) {

  }

  @Override
  public void afterTextChanged(Editable s) {

  }
});
複製代碼

可是每每有時,咱們只須要afterTextChanged監聽,並不須要其餘兩個,但因爲接口的限制,咱們不得不所有寫出將其實現。致使書寫體驗和閱讀體驗降低。性能

那麼在kotlin中咱們能夠騷操做:學習

editText.onTextChange {
	afterTextChanged { s ->

	}
}
複製代碼

確定有小夥伴,是這個表情:ui

https://user-gold-cdn.xitu.io/2019/6/8/16b3554d466d9837?w=360&h=360&f=jpeg&s=13317

那麼這是如何實現的呢,首先,自定義個類,繼承TextWatcherspa

class TextWatcherDsl : TextWatcher {
    private var afterTextChanged: ((s: Editable?) -> Unit)? = null
    private var beforeTextChanged: ((s: CharSequence?, start: Int, count: Int, after: Int) -> Unit)? =
        null
    private var onTextChanged: ((s: CharSequence?, start: Int, before: Int, count: Int) -> Unit)? =
        null

    override fun afterTextChanged(s: Editable?) {
        afterTextChanged?.invoke(s)
    }

    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
        beforeTextChanged?.invoke(s, start, count, after)
    }

    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
        onTextChanged?.invoke(s, start, before, count)
    }

    fun afterTextChanged(after: (s: Editable?) -> Unit) {
        afterTextChanged = after
    }

    fun beforeTextChanged(before: (s: CharSequence?, start: Int, count: Int, after: Int) -> Unit) {
        beforeTextChanged = before
    }

    fun onTextChanged(onChanged: (s: CharSequence?, start: Int, before: Int, count: Int) -> Unit) {
        onTextChanged = onChanged
    }
}

複製代碼

這裏面涉及到kotlin的參數方法內容(即:方法能夠直接做爲參數傳遞進),不懂自行百度,再也不講解。code

接下來,來實現一個DSL的擴展方法:orm

inline fun EditText.onTextChange(textWatcher: TextWatcherDsl.() -> Unit): TextWatcher {
    val watcher = TextWatcherDsl().apply(textWatcher)
    addTextChangedListener(watcher)
    return watcher
}
複製代碼

ok,搞定了,全部的EditText都具備了onTextChange方法,監聽文本的方法須要什麼寫什麼。

  • 一、擴展方法再也不具體解釋,不是本文重點

  • 二、這裏的inline是指內聯方法,即:在編譯時期,代碼會直接插入掉用處,實際上不是調用外部方法。也就不會形成調用外部方法而致使的性能開銷,有興趣的小夥伴能夠百度了學習。

這裏須要注意理解下參數TextWatcherDsl.() -> UnitTextWatcherDsl是咱們剛剛自定義的類,而後後面跟了一個,就是說,這個參數能夠接收TextWatcherDsl類裏的全部方法,只要是它裏面的方法均可以傳遞進來。

SharedPreferences

咱們再來看下Google官方對於SharedPreferences的擴展。慣例,咱們Java中使用SP寫入數據是這樣的:

SharedPreferences sp = getSharedPreferences("demo", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putString("key1", "value1");
editor.putString("key2", "value2");
editor.apply();
複製代碼

kotlin中是這樣的:

val sp = getSharedPreferences("demo", Context.MODE_PRIVATE)
sp.edit {
    putString("key1", "value1")
    putString("key2", "value2")
}
複製代碼

是否是簡單易讀。

https://user-gold-cdn.xitu.io/2019/6/8/16b3554dc9725c58?w=1141&h=640&f=jpeg&s=19829

咱們來看下官方Google是如何實現的這個方法:

inline fun SharedPreferences.edit( commit: Boolean = false, action: SharedPreferences.Editor.() -> Unit
) {
    val editor = edit()
    action(editor)
    if (commit) {
        editor.commit()
    } else {
        editor.apply()
    }
}
複製代碼

是的,沒錯就這麼點。

參數SharedPreferences.Editor後面跟了一個,能夠接受SharedPreferences.Editor中的方法,例如putString

File

上面的寫法,會kotlin的小夥伴應該都見過了。接下來,我來展現下另外一種DSL的寫法,可能大家會不多用。

這裏我操做File文件的方法來展現。這裏我再也不寫java代碼。

常規寫法

首先咱們看一下常規拷貝文件的寫法:

fun copyTo(form:File, to: File) {
    // 具體操做文件拷貝的代碼
}
複製代碼

使用:

copyTo(file1, file2)
複製代碼

這種太常見了,Java裏也是如此操做的,不細說了。

kotlin擴展寫法

接下來改造下,寫成擴展方法:

fun File.copyTo(to: File) {
    // 具體操做文件拷貝的代碼
}
複製代碼

使用:

file1.copyTo(file2)
複製代碼

看起來好像舒服了那麼一點

終極寫法

infix fun File.copyTo(to: File) {
    // 具體操做文件拷貝的代碼
}
複製代碼

使用:

file1 copyTo file2
複製代碼

注意看擴展方法前面多了一個infix來修飾方法,是否是很是接近了咱們人類說話時的語言方式。

大家的表情是這樣的:

https://user-gold-cdn.xitu.io/2019/6/8/16b3554dc6182fed?w=301&h=270&f=jpeg&s=7791

相似的方法,在anko庫中中也有不少地方使用,多去閱讀源碼就會發現。

本次的簡介就到此爲此,但願經過直接的代碼展現,能讓各位找到些感受

相關文章
相關標籤/搜索