1. 程式人生 > >Kotlin詳解:第三章,實戰

Kotlin詳解:第三章,實戰

一,搭建開發環境

1,安裝Android Studio 3.0及以上版本
2,升級Gradle外掛版本至少為4.1
3,升級Kotlin外掛版本
4,工程配置
①,配置工程build.gradle

buildscript {

    ext.kotlin_version = '1.1.51'//指定Kotlin的編譯版本
    ext.anko_version="0.9"//指定Anko庫的版本號
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.3'

        //指定Kotlin外掛的路徑
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
    }
}

②,配置專案build.gradle

     //引入外掛
     apply plugin: 'kotlin-android'
     apply plugin: 'kotlin-android-extensions'
     //庫編譯版本
     implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
     implementation "org.jetbrains.anko:anko-common:$anko_version"

③,編寫Activity,這就是Activity程式碼和Java方式基本一樣,只是Kotlin用 “ :” 替代了extends,還有類的過載用override

class MainActivity : AppCompatActivity() {

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

}

二,常用控制元件使用

1,Button
①,基本使用

        //anko庫支援直接用控制元件名button的方式,省去了findViewById
        button.text = "這是個按鈕"
        //點選事件,不需要檢視方式
        button.setOnClickListener {
            button.text = "你點了一下"
        }

②,匿名函式方法

        //點選事件,需要傳入檢視方式。“->” 前邊是型別引數相當於View,後邊是事件的具體實現
        //模板表示式 ${""}
        button.setOnClickListener { v ->
            toast("點選了控制元件:${(v as Button).text}")
        }

③,內部類

class Main2Activity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)
        //點選事件,內部類方式
        button.setOnClickListener(MyClickListener())

    }
    //Kotlin關鍵字 inner 是標記該類為內部類,和Java內部類一樣。
    // 如果不用inner關鍵字,就是巢狀類,巢狀類不能訪問外部類成員
    private inner class MyClickListener : View.OnClickListener {
        override fun onClick(v: View) {
            toast("點選了控制元件:${(v as Button).text}")
        }
    }
}

2,複選框CheckBox

        //isChecked可以設定狀態也可以獲取狀態
        checkbox.isChecked = false
        //複選框點選事件
        checkbox.setOnCheckedChangeListener { v, isChecked ->
            checkbox.text = "你${if (isChecked) "勾選" else "取消"}了複選框"
        }

3,自定義控制元件

三,Kotlin實現資料儲存

1,全域性Application
①,在App執行中,Application貫穿應用的整個生命週期,我們經常會用到全域性Application,通常我們會把Application實現單例模式
②,單例化第一種方式

class App : Application() {
    override fun onCreate() {
        super.onCreate()
        instance=this
    }
    companion object {
        //實現一:宣告可空屬性
        private var instance:App?=null
        fun instance()=instance!!
        //實現二:宣告延遲初始化屬性
        //private lateinit var instance:App
        //fun instance()= instance
    }
}

③,單例化第二種方式

class App : Application() {
    override fun onCreate() {
        super.onCreate()
        instance = this
    }
    //藉助Delegates的委託屬性單例化
    companion object {
        private var instance: App by Delegates.notNull()
        fun instance() = instance
    }
}

④,單例化第三種方式(自定義代理)
一般前兩種在大多數情況下是可以的,但是還不夠嚴格

class App : Application() {
    override fun onCreate() {
        super.onCreate()
        instance = this
    }

    //自定義一個非空且只能一次性賦值的委託屬性
    companion object {
        private var instance: App by NotNullSingleValueVar()
        fun instance() = instance
    }

    private class NotNullSingleValueVar<T>() : ReadWriteProperty<Any?, T> {
        private var value: T? = null
        override fun getValue(thisRef: Any?, property: KProperty<*>): T {
            return value ?: throw IllegalStateException("application not initialized")
        }

        override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
            this.value = if (this.value == null) value
            else throw IllegalStateException("application already initialized")
        }

    }
}

2,SharedPreferences

單獨寫個類實現SharedPreferences

class Preference<T>(val context: Context, val name: String, val default: T) : ReadWriteProperty<Any?, T> {
    //通過屬性代理初始化共享引數物件
    val prefs: SharedPreferences by lazy { context.getSharedPreferences("default", Context.MODE_PRIVATE) }

    //接管屬性值的獲取行為
    override fun getValue(thisRef: Any?, property: KProperty<*>): T {
        return findPreference(name, default)
    }
    //接管屬性值的修改行為
    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        putPreference(name, value)
    }
    //利用with函式定義臨時的名稱空間
    private fun <T> findPreference(name: String, default: T): T = with(prefs) {
        val res: Any = when (default) {
            is Long -> getLong(name, default)
            is String -> getString(name, default)
            is Int -> getInt(name, default)
            is Boolean -> getBoolean(name, default)
            is Float -> getFloat(name, default)
            else -> throw IllegalArgumentException("This type can be saved saved Preferences")
        }
        return res as T
    }
    private fun <T> putPreference(name: String, value: T) = with(prefs.edit()) {
        when (value) {
            is Long -> putLong(name, value)
            is String -> putString(name, value)
            is Int -> putInt(name, value)
            is Boolean -> putBoolean(name, value)
            is Float -> putFloat(name, value)
            else -> throw IllegalArgumentException("This type can be saved into Preferences")
        }.apply()
    }
}

使用Preference進行資料儲存

class MainActivity : AppCompatActivity() {
    //儲存名字
    private var name: String by Preference(this, "name", "")
    //儲存年齡
    private var age: Int by Preference(this, "age", 0)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)
        //isChecked可以設定狀態也可以獲取狀態
        checkbox.isChecked = false
        //複選框點選事件
        checkbox.setOnCheckedChangeListener { v, isChecked ->
            //儲存資料
            name = "小名"
            age = 28

        }
        //獲取資料
        checkbox.text = "姓名:${name},年齡:${age}"
    }


}

3,檔案I/O操作
Kotlin檔案讀取常用方法

  • readText():讀取整個檔案內容
  • readLines():按行讀取,返回字串集合
  • readBytes():得到檔案位元組陣列
  • writeText():寫入檔案
  • walk():得到檔案樹
        //讀取檔案內容,可以指定編碼格式
        val content = File("檔案路徑").readText(Charset.forName("UTF-8"))
        //按行讀取 讀取前三行
        var strs: List<String> = File("檔案路徑").readLines().take(3)
        //寫檔案
        File("檔案路徑").writeText("寫入內容")
        //遍歷檔案目錄
        val fileTree: FileTreeWalk = File("路徑").walk()
        fileTree.maxDepth(1)//遍歷目錄層級為1,不需要遍歷子目錄
                .filter { it.isFile }//只選擇檔案,不包含目錄
                .filter { it.extension == "txt" }//選擇副檔名為txt的文字檔案
                //.filter { it.extension in listOf("png", "jpg") }//選擇副檔名為png和jpg的圖片檔案