Kotlin在項目中的應用和踩過的坑

應用

  • 空類型安全

    Kotlin引入了可空類型(用排抬?標識)竖般,在編譯期杜絕了可空類型直接調用方法的可能。

    var a: String = "abc"
    a = null // 編譯錯誤
    
    var b: String? = "abc"
    b = null // ok
    
    val l = a.length
    
    val l = b.length // 錯誤:變量“b”可能為空
    val l = b?.length ?: 0
    
  • 鏈式調用

    靈活使用Kotlin提供的let洞渔、apply赊淑、takeIf這些方法国旷,用鏈式調用的方式組織代碼误趴,可以將一大串邏輯分割成幾塊。

    File(url).takeIf { it.exists() }
            ?.let {
                JSONObject(NetworkUtils.postFile(SERVER_URL, url))
            }?.takeIf { it.optString("message") == "success" }
            ?.let {
                post(it.optString("result"))
            } ?: mHandler.post { view?.onFail() }
    
  • 默認參數

    普通的帶有默認參數的方法Java是無法調用的蓬抄,因為Kotlin對默認參數的處理并不是生成多個方法丰嘉,而是給方法添加幾個額外參數記錄調用者傳遞了多少參數,加上了JvmOverloads這個注解之后才會生成多個方法供Java調用嚷缭。并且Kotlin調用方法可以指定參數名饮亏。

    class CustomLayout @JvmOverloads constructor(
            context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
    ) : FrameLayout(context, attrs, defStyleAttr), LifeCycleMonitor {
        // pass
    }
    
  • 擴展方法

    擴展方法在項目里使用得比較少,但是Kotlin提供的很多語法糖都是利用擴展方法實現的阅爽,例如forEach路幸、let之類的方法。擴展方法的原理是生成一個靜態(tài)方法付翁。

    // _Collections.kt里的擴展方法
    /**
     * Performs the given [action] on each element.
     */
    @kotlin.internal.HidesMembers
    public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit {
        for (element in this) action(element)
    }
    
  • 操作符重載

    Kotlin會將一些常用的表達式翻譯為方法調用劝赔,最常用的有將 list[0] 翻譯成 list.get(0) ,將 map[0] = someObject 翻譯成 map.set(0, someObject)胆敞。實際上任意實現operator fun get(a : Any) : Any 和 operator fun set(a : Any, b : Any) 方法的類都可以使用以上兩種表達式着帽。

    // 操作符重載在Kotlin的語法中隨處可見,下面這個例子說明了
    for (i in 1..10) {
        // pass
    }
    // 是如何工作的移层,首先明白表達式 .. 對應 rangeTo 方法仍翰,表達式 in 對應 contains 方法
     
    // 在Primitives.kt文件中的Int類里
     /** Creates a range from this value to the specified [other] value. */
    public operator fun rangeTo(other: Int): IntRange
     
    // 在IntRange類里可以發(fā)現 in 這個表達式對應的方法調用 contains
    public class IntRange(start: Int, endInclusive: Int) : IntProgression(start, endInclusive, 1), ClosedRange<Int> {
        override val start: Int get() = first
        override val endInclusive: Int get() = last
     
        override fun contains(value: Int): Boolean = first <= value && value <= last
    

    Kotlin中操作符重載所有表達式與方法調用對應關系

  • 不再使用findViewById

    在build.gradle中添加 apply plugin:'kotlin-android-extensions' 就可以直接在代碼中用View的id來代替這個View對象。

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        iv_feedback.setOnClickListener(this)
        iv_back.setOnClickListener(this)
        btn_feedback.setOnClickListener(this)
    

    反編譯發(fā)現观话,這種用法的原理是Kotlin會自動生成findViewById的代碼予借,在Activity、Fragment和自定義View中Kotlin會使用一個map緩存每次查找到的View频蛔,避免每次調用View的方法都會重新調用一次findViewById灵迫,但是需要注意的是通過View.id這種方式獲取子View的時候沒有緩存,所以在RecyclerView的ViewHolder中都會使用一個屬性來存儲ItemView的某個子View晦溪。

    // Activity中的邏輯
    public View _$_findCachedViewById(int var1) {
       if(this._$_findViewCache == null) {
          this._$_findViewCache = new HashMap();
       }
     
       View var2 = (View)this._$_findViewCache.get(Integer.valueOf(var1));
       if(var2 == null) {
          // Fragment的代碼中這里會調用getView.findViewById瀑粥,所以通過id調用方法需要在onCreateView生命周期之后使用
          var2 = this.findViewById(var1);
          this._$_findViewCache.put(Integer.valueOf(var1), var2);
       }
     
       return var2;
    }
    
    // RecyclerView的ViewHolder中都會使用一個屬性來存儲ItemView的某個子View
    private val mLabelImage = itemView.label_image
    private val mLabelType = itemView.label_type
    
  • 與屬性相關的一些改變

  • 自帶getter/setter

    Kotlin類里的屬性自帶getter/setter,訪問權限可以修改三圆,也可以重寫get/set方法

     var someString : String
        get() = "this${toString()}"
        protected set(value) {
            Log.e(TAG, "setValue$value")
            field = value
        }
    
  • 可以定義在類聲明里
    open class Message(val id: Long,
                           val type: Int,
                           val time: Long,
                           val status : Int)
    
  • lateInit和by lazy

對于一些沒有在構造函數里賦值的非空類型對象狞换,可以使用lateinit和by lazy來延遲初始化。

Java調用Kotlin方法時空類型不再安全

Java里調用kotlin方法舟肉,空對象傳遞給Kotlin的非可空參數會拋異常修噪,但是Kotlin無法判斷Java傳遞的對象是否可能為空,所以編譯器不會報異常路媚。在將Java工程轉變成Kotlin工程的過程中不能忽略這個坑黄琼。

更多

協(xié)程

Anko Layouts代替xml

verticalLayout {
   val name = editText()
   button("Say Hello") {
       onClick { toast("Hello, ${name.text}!") }
   }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市整慎,隨后出現的幾起案子脏款,更是在濱河造成了極大的恐慌围苫,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件弛矛,死亡現場離奇詭異够吩,居然都是意外死亡比然,警方通過查閱死者的電腦和手機丈氓,發(fā)現死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來强法,“玉大人万俗,你說我怎么就攤上這事∫樱” “怎么了闰歪?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蓖墅。 經常有香客問我库倘,道長,這世上最難降的妖魔是什么论矾? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任教翩,我火速辦了婚禮,結果婚禮上贪壳,老公的妹妹穿的比我還像新娘饱亿。我一直安慰自己,他們只是感情好闰靴,可當我...
    茶點故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布彪笼。 她就那樣靜靜地躺著,像睡著了一般蚂且。 火紅的嫁衣襯著肌膚如雪配猫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天杏死,我揣著相機與錄音章姓,去河邊找鬼。 笑死识埋,一個胖子當著我的面吹牛凡伊,可吹牛的內容都是我干的。 我是一名探鬼主播窒舟,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼系忙,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了惠豺?” 一聲冷哼從身側響起银还,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤风宁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蛹疯,有當地人在樹林里發(fā)現了一具尸體戒财,經...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年捺弦,在試婚紗的時候發(fā)現自己被綠了饮寞。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,567評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡列吼,死狀恐怖幽崩,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情寞钥,我是刑警寧澤慌申,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站理郑,受9級特大地震影響蹄溉,放射性物質發(fā)生泄漏。R本人自食惡果不足惜您炉,卻給世界環(huán)境...
    茶點故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一柒爵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧邻吭,春花似錦餐弱、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至畸写,卻和暖如春驮瞧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背枯芬。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工论笔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人千所。 一個月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓狂魔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親淫痰。 傳聞我的和親對象是個殘疾皇子最楷,可洞房花燭夜當晚...
    茶點故事閱讀 45,585評論 2 359

推薦閱讀更多精彩內容