1. 程式人生 > >Kotlin Android 實戰(一)閃屏頁面

Kotlin Android 實戰(一)閃屏頁面

看了一些kotlin的語法,但是總覺得不真正寫一下不行。

聽說kotlin和java完全相容,寫了寫發現,最小單位是類(java類中不能寫kotlin程式碼,反之亦然)。

想在新專案中嘗試一下的同學不要有顧慮,就像當初使用mvvm,mvp一樣,實在不行在換回java唄(哈哈哈)。

本篇從kotlin安裝開始到編寫一個簡單的閃屏頁面練練。

首先AS安裝kotlin外掛:


然後重啟as,在專案的project的gradle中新增:

classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.2"


然後是app下的gradle中新增:

apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
kapt {
    generateStubs = true
}
dependencies {
    .../
    kapt 'com.android.databinding:compiler:2.3.0'
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
}

然後建立一個Activity,這時建立的activity就不是我們原來的.class檔案了,建立的是.kt檔案:


我這裡建立了一個叫SplashActivity。

建立之後,分析下我們閃屏會用到Handler來發送延時訊息,直接使用handler可能會造成記憶體洩漏,所以我們去自定義個弱引用的handler。

原來java的寫法:

/**
 * 採用弱引用handler 防止記憶體洩漏
 * Created by ge on 2017/2/16.
 */

public class UIHandler<T> extends Handler {

    protected WeakReference<T> ref;

    public UIHandler(T cls){
        ref = new WeakReference<T>(cls);
    }

    public T getRef(){
        return ref != null ? ref.get() : null;
    }

}

改成kotlin之後:
/**
 * 採用弱引用handler 防止記憶體洩漏
 * Created by ge on 2017/2/16.
 */

open class UIHandler<T>(cls: T) : Handler() {

    protected var ref: WeakReference<T>? = null

    init {
        ref = WeakReference(cls)
    }

    fun getRef(): T? {
        return if (ref != null) ref!!.get() else null
    }

}

可能一開始,我們直接轉會遇到很多語法上的問題,as給我們提供了一個便捷通道,一鍵直接從java檔案轉成kotlin檔案:



我建議,大家如果是跟我一樣剛開始接觸,還是試著練習一點點寫,鍛鍊鍛鍊,如果實在寫不出來就轉換之後有個參照(小白小白小白)。

而且自動轉換畢竟是按照你不知道的規則轉,轉的對錯與否我也不知道。

好了,定義完handler之後就在SplashActivity中使用了,首先定義幾個常量:

 // 將常量放入這裡
    companion object {

        // 正常跳轉到登入介面 常量 防止以後增加業務邏輯
        val MSG_LAUNCH : Int = 0

        // 延時時間
        val SLEEP_TIME = 3000
    }

再定義我們的Handler:
private class SplashHandle(cls : SplashActivity) : UIHandler<SplashActivity>(cls) {

        override fun handleMessage(msg: Message?) {
            super.handleMessage(msg)
            val activity = ref?.get()
            if (null != activity){

                if (activity.isFinishing)
                    return

                when(msg?.what){

                    // 正常跳轉到登入介面
                    MSG_LAUNCH -> {
                        activity.startActivity(Intent(activity, LoginActivity::class.java))
                        activity.finish()
                    }
                }
            }
        }
    }

注:java中的switch換成了when。

private val mHandler = SplashHandle(this)

定義runnable:
 val runnable = Runnable {
        kotlin.run {
            val message = mHandler.obtainMessage(MSG_LAUNCH)
            mHandler.sendMessage(message)
        }
    }

注:這裡出現了var 和 val兩個宣告欄位,

var是宣告可變的變數。

val是宣告一個只讀變數,可以理解為java中的final,宣告的時候必須初始化,生命之後不能改變她的值。

一系列準備工作做好之後就是最後一步呼叫了,我這裡在onResume中使用:

 override fun onResume() {
        super.onResume()

        val start = System.currentTimeMillis()

        /*
        這裡計算了兩個時間
        兩個時間間可以放入判斷條件:是否需要自動登入等
         */

        var costTime = System.currentTimeMillis() - start

        val left = SLEEP_TIME - costTime

        // kotlin中取消了java中的三目運算,換成if...else...
        mHandler.postDelayed(runnable, if(left > 0) left else 0)
    }

上面沒有提到我們Activity的頭部(onCreate),因為裡面只有一個setContentView。

setContentView和原來沒啥區別,除了java檔案替換成.kt檔案之外的檔案都沒有變。

最後貼出閃屏頁面的完整程式碼:

package com.reliable.mihophysical.ui

import android.content.Intent
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.os.Message
import com.reliable.baselib.utils.UIHandler

import com.reliable.mihophysical.R
import com.reliable.mihophysical.ui.login.LoginActivity

/**
 * 閃屏介面
 * by ge
 */
class SplashActivity : AppCompatActivity() {

    private val mHandler = SplashHandle(this)

    // 將常量放入這裡
    companion object {

        // 正常跳轉到登入介面 常量 防止以後增加業務邏輯
        val MSG_LAUNCH : Int = 0

        // 延時時間
        val SLEEP_TIME = 3000
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_splash)

    }

    override fun onResume() {
        super.onResume()

        val start = System.currentTimeMillis()

        /*
        這裡計算了兩個時間
        兩個時間間可以放入判斷條件:是否需要自動登入等
         */

        var costTime = System.currentTimeMillis() - start

        val left = SLEEP_TIME - costTime

        // kotlin中取消了java中的三目運算,換成if...else...
        mHandler.postDelayed(runnable, if(left > 0) left else 0)
    }


    val runnable = Runnable {
        kotlin.run {
            val message = mHandler.obtainMessage(MSG_LAUNCH)
            mHandler.sendMessage(message)
        }
    }

    // 弱引用handler內部類
    private class SplashHandle(cls : SplashActivity) : UIHandler<SplashActivity>(cls) {

        override fun handleMessage(msg: Message?) {
            super.handleMessage(msg)
            val activity = ref?.get()
            if (null != activity){

                if (activity.isFinishing)
                    return

                when(msg?.what){

                    // 正常跳轉到登入介面
                    MSG_LAUNCH -> {
                        activity.startActivity(Intent(activity, LoginActivity::class.java))
                        activity.finish()
                    }
                }
            }
        }
    }
}