【譯】Kotlin Android擴展(Kotlin Android Extensions)(四)

轉(zhuǎn)自:http://ranseti.top/article/extensions

本教程介紹如何使用Kotlin Android擴展來改進對Android開發(fā)的支持滥沫。

在本教程中,我們將介紹使用Kotlin Android Extensions插件所需的步驟键俱,從而增強Android的開發(fā)體驗兰绣。



View綁定

背景

每個Android開發(fā)人員都知道findViewById()函數(shù)。 毫無疑問编振,這是一個難以閱讀和支持的潛在錯誤和惡劣代碼的來源缀辩。 雖然有幾個庫可用于解決這個問題,但是這些庫需要為每個暴露的View注釋字段踪央。

Kotlin Android Extensions插件使我們能夠獲得與其中一些庫相同的體驗臀玄,而不必添加任何額外的代碼。

實質(zhì)上畅蹂,這允許以下代碼:

// Using R.layout.activity_main from the 'main' source set
import kotlinx.android.synthetic.main.activity_main.*

class MyActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // Instead of findViewById<TextView>(R.id.textView)
        textView.setText("Hello, world!")
    }
}

使用Kotlin Android擴展

  • 配置依賴關(guān)系

在本教程中健无,我們將使用Gradle,但使用IntelliJ IDEA項目結(jié)構(gòu)或Maven也可以完成相同的任務(wù)液斜。 有關(guān)設(shè)置Gradle以使用Kotlin的詳細信息累贤,請參閱使用Gradle叠穆。

Android擴展是IntelliJ IDEA和Android Studio的Kotlin插件的一部分。 你不需要安裝額外的插件畦浓。

您只需在模塊的build.gradle文件中啟用Android擴展Gradle插件即可:

apply plugin: 'kotlin-android-extensions'
  • 導(dǎo)入合成屬性

一次性導(dǎo)入特定布局的所有小部件屬性非常方便:

import kotlinx.android.synthetic.main.<layout>.*

因此痹束,如果布局文件名是activity_main.xml,我們會導(dǎo)入kotlinx.android.synthetic.main.activity_main讶请。*祷嘶。

如果我們想調(diào)用View的綜合屬性,我們也應(yīng)該導(dǎo)入kotlinx.android.synthetic.main.activity_main.view夺溢。*论巍。

一旦我們這樣做,我們就可以調(diào)用相應(yīng)的擴展风响,它們是以XML文件中的視圖命名的屬性嘉汰。 例如,對于這個view:

<TextView
        android:id="@+id/hello"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>

將會有一個名為hello的屬性:

activity.hello.text = "Hello World!"
  • 實驗?zāi)J?Experimental Mode)

Android擴展插件包含幾個實驗性功能状勤,如LayoutContainer支持和Parcelable實現(xiàn)生成器鞋怀。 這些功能尚未被視為生產(chǎn)準備,所以您需要打開build.gradle中的實驗?zāi)J讲拍苁褂盟鼈儯?/p>

androidExtensions {
    experimental = true
}
  • LayoutContainer支持

Android擴展插件支持不同類型的容器持搜。 最基本的是Activity密似,F(xiàn)ragment和View,但是通過實現(xiàn)LayoutContainer接口葫盼,你可以把(虛擬的)任何類轉(zhuǎn)換成一個Android Extensions容器残腌,例如:

import kotlinx.android.extensions.LayoutContainer

class ViewHolder(override val containerView: View) : ViewHolder(containerView), LayoutContainer {
    fun setup(title: String) {
        itemTitle.text = "Hello World!"
    }
}

請注意,您需要打開實驗標志才能使用LayoutContainer贫导。

  • Flavor支持

Android擴展插件支持Android風格抛猫。 假設(shè)你在build.gradle文件中有一個free的名字:

android {
    productFlavors {
        free {
            versionName "1.0-free"
        }
    }
}

因此,您可以通過添加以下導(dǎo)入來導(dǎo)入free / res / layout / activity_free.xml布局的所有合成屬性:

import kotlinx.android.synthetic.free.activity_free.*

在實驗?zāi)J街泻⒌疲梢灾付ㄈ魏巫凅w名稱(不僅味道)闺金,例如 freeDebug或freeRelease也可以工作。

  • View 緩存(View Caching)

調(diào)用findViewById()可能會很慢钱反,特別是在視圖層次很大的情況下掖看,所以Android擴展嘗試通過在容器中緩存視圖來最小化findViewById()調(diào)用。

默認情況下面哥,Android擴展為在Kotlin中編寫的每個容器(Activity哎壳,F(xiàn)ragment,View或LayoutContainer實現(xiàn))添加一個隱藏緩存函數(shù)和一個存儲字段尚卫。 該方法是相當小归榕,所以它不會增加APK的大小。

在以下示例中吱涉,findViewById()僅調(diào)用一次:

class MyActivity : Activity()

fun MyActivity.a() { 
    textView.text = "Hidden view"
    textView.visibility = View.INVISIBLE
}

但在以下情況下:

fun Activity.b() { 
    textView.text = "Hidden view"
    textView.visibility = View.INVISIBLE
}

我們不知道這個函數(shù)是否只會被我們的來源的活動或簡單的Java活動調(diào)用刹泄。 因此外里,即使前面的示例中的MyActivity實例作為接收者傳遞,我們也不使用緩存特石。

  • 更改視圖緩存策略

您可以更改全局或每個容器的緩存策略盅蝗。 這也需要開啟實驗?zāi)J健?/p>

項目全局緩存策略在build.gradle文件中設(shè)置:

androidExtensions {
    defaultCacheImplementation = "HASH_MAP" // also SPARSE_ARRAY, NONE
}

默認情況下,Android擴展插件使用HashMap作為后備存儲姆蘸,但是您可以切換到SparseArray實現(xiàn)墩莫,或者關(guān)閉緩存。 當您僅使用Android擴展的Parcelable部分時逞敷,后者特別有用狂秦。

另外,你可以使用@ContainerOptions注解一個容器來改變它的緩存策略:

import kotlinx.android.extensions.ContainerOptions

@ContainerOptions(cache = CacheImplementation.NO_CACHE)
class MyActivity : Activity()

fun MyActivity.a() { 
    // findViewById() will be called twice
    textView.text = "Hidden view"
    textView.visibility = View.INVISIBLE
}



Parcelable

從Kotlin 1.1.4開始推捐,Android擴展插件提供了Parcelable實現(xiàn)生成器作為實驗性功能裂问。

  • 啟用Parcelable支持

如上所述應(yīng)用kotlin-android-extensions Gradle插件并打開實驗標志。

  • 如何使用

使用@Parcelize對類進行注釋牛柒,并自動生成一個Parcelable實現(xiàn)堪簿。

import kotlinx.android.parcel.Parcelize

@Parcelize
class User(val firstName: String, val lastName: String, val age: Int): Parcelable

@Parcelize需要在主構(gòu)造函數(shù)中聲明所有序列化的屬性。 Android擴展將在每個屬性上發(fā)出警告皮壁,并在類體中聲明一個后臺字段戴甩。 此外,如果某些主構(gòu)造函數(shù)參數(shù)不是屬性闪彼,則不能應(yīng)用@Parcelize。

如果你的類需要更高級的序列化邏輯协饲,你可以把它寫在一個伴隨類中:

@Parcelize
data class Value(val firstName: String, val lastName: String, val age: Int) : Parcelable {
    private companion object : Parceler<User> {
        override fun User.write(parcel: Parcel, flags: Int) {
            // Custom write implementation
        }

        override fun create(parcel: Parcel): User {
            // Custom read implementation
        }
    }
}
  • 支持的類型

@Parcelize支持多種類型:

原始類型(及其盒裝版本);
對象和枚舉;
字符串畏腕,CharSequence;
例外;
Size,SizeF茉稠,Bundle描馅,IBinder,IInterface而线,F(xiàn)ileDescriptor;
SparseArray铭污,SparseIntArray,SparseLongArray膀篮,SparseBooleanArray;
所有的Serializable(是的嘹狞,Date也支持)和Parcelable實現(xiàn);
所有支持類型的集合:List(映射到ArrayList),Set(映射到LinkedHashSet)誓竿,Map(映射到LinkedHashMap);
還有一些具體的實現(xiàn):ArrayList磅网,LinkedList,SortedSet筷屡,NavigableSet涧偷,HashSet簸喂,LinkedHashSet,TreeSet燎潮,SortedMap喻鳄,NavigableMap,HashMap确封,LinkedHashMap除呵,TreeMap,ConcurrentHashMap;
所有支持類型的數(shù)組;
所有受支持類型的可空版本隅肥。

  • 自定義Parcelers

即使你的類型不被直接支持竿奏,你也可以為它編寫一個Parceler映射對象。

class ExternalClass(val value: Int)

object ExternalClassParceler : Parceler<ExternalClass> {
    override fun create(parcel: Parcel) = ExternalClass(parcel.readInt())

    override fun ExternalClass.write(parcel: Parcel, flags: Int) {
        parcel.writeInt(value)
    }
}

可以使用@TypeParceler或@WriteWith注釋應(yīng)用外部parcelers :

// Class-local parceler
@Parcelable
@TypeParceler<ExternalClass, ExternalClassParceler>()
class MyClass(val external: ExternalClass)

// Property-local parceler
@Parcelable
class MyClass(@TypeParceler<ExternalClass, ExternalClassParceler>() val external: ExternalClass)

// Type-local parceler
@Parcelable
class MyClass(val external: @WriteWith<ExternalClassParceler>() ExternalClass)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末腥放,一起剝皮案震驚了整個濱河市泛啸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌秃症,老刑警劉巖候址,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異种柑,居然都是意外死亡岗仑,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門聚请,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荠雕,“玉大人,你說我怎么就攤上這事驶赏≌ū埃” “怎么了?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵煤傍,是天一觀的道長盖文。 經(jīng)常有香客問我,道長蚯姆,這世上最難降的妖魔是什么五续? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮龄恋,結(jié)果婚禮上疙驾,老公的妹妹穿的比我還像新娘。我一直安慰自己郭毕,他們只是感情好荆萤,可當我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般链韭。 火紅的嫁衣襯著肌膚如雪偏竟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天敞峭,我揣著相機與錄音踊谋,去河邊找鬼。 笑死旋讹,一個胖子當著我的面吹牛殖蚕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播沉迹,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼睦疫,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了鞭呕?” 一聲冷哼從身側(cè)響起蛤育,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎葫松,沒想到半個月后瓦糕,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡腋么,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年咕娄,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片珊擂。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡圣勒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出摧扇,到底是詐尸還是另有隱情灾而,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布扳剿,位于F島的核電站,受9級特大地震影響昼激,放射性物質(zhì)發(fā)生泄漏庇绽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一橙困、第九天 我趴在偏房一處隱蔽的房頂上張望瞧掺。 院中可真熱鬧,春花似錦凡傅、人聲如沸辟狈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽哼转。三九已至明未,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間壹蔓,已是汗流浹背趟妥。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留佣蓉,地道東北人披摄。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像勇凭,于是被迫代替她去往敵國和親疚膊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,802評論 2 345