kotlin小白日記2「工具類的封裝,Anko簡化吐司,空值處理」

weixin_33918357發表於2018-09-16

Kotlin初體驗二「kotlin框架Anko的使用,工具類的封裝,空值處理」

本篇上篇為kotlin初體驗,原始碼已上傳至Github倉庫的KotlinPractice2資料夾內

AndroidStudio是可以直接執行Main主函式類的,建立test包,在包下建立dmeo1.kt檔案,輸入以下程式碼

/**
 * 輸入main提示輸出主函式
 * 輸入sout輸出println
 */
fun main(args: Array<String>) {
    println("你好,世界")
}

右鍵Run就可以執行主函式中的程式碼了

4002920-514ded2f2a35336d.gif
AndroidStudio執行單個類.gif

頁面佈局

建立專案,在activity_main.xml下新增4個按鈕

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btnLog"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="封裝Log" />

    <Button
        android:id="@+id/btnToasts"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="短吐司"
        />

    <Button
        android:id="@+id/btnToastL"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="長吐司"
        />

    <Button
        android:id="@+id/btnNet"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="獲取網路資料"
        />

</LinearLayout>

新增按鈕的點選事件

package com.example.tonjies.kotlinpractice2

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.view.View
//有了這一行後就不需要再寫findById了
import kotlinx.android.synthetic.main.activity_main.*
//實現OnClickListener點選事件介面
class MainActivity : AppCompatActivity(), View.OnClickListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //初始化按鈕
        init()
    }

    //初始化按鈕
    private fun init() {
        btnLog.setOnClickListener(this)
        btnToasts.setOnClickListener(this)
        btnToastL.setOnClickListener(this)
        btnNet.setOnClickListener(this)
    }

    //實現按鈕的點選事件
    override fun onClick(v: View?) {
        when (v?.id) {
            //使用封裝的工具類列印Log
            R.id.btnLog -> {
                
            }
            //使用Anko框架輸出短吐司
            R.id.btnToasts -> {

            }
            //使用Anko框架資料長吐司
            R.id.btnToastL -> {

            }
            //獲取網路資料
            R.id.btnNet -> {

            }
        }
    }

}

工具類的封裝

為什麼要封裝Log,這是因為我們每次輸入Log的時候,每次都要重複的輸入TAG,我們可以把Log封裝成一個工具類,把固定的TAG變數抽取出來

在Kotlin中可以將類的關鍵字class替換成object,這樣該類就會變成了一個單例模式的類,之後我們就可以接用使用類名.方法()的形式呼叫該類中的方法了

/**
 * 在kotlin中,加了object後,L類就成為了一個單例模式的類,相當於幫我們省略掉了以前Java實現單例的程式碼
 * 最後我們可以直接L.d呼叫類中的方法
 */
object L {
    //過濾詞
    val TAG:String="tonjies"
    //5個等級 DIWE

    fun d(text: String) {
        Log.d(TAG, text + "")
    }
}

在Log按鈕的點選事件裡面使用

override fun onClick(v: View?) {
    when (v?.id) {
        R.id.btnLog -> {
            //加了object關鍵字後成為了單例模式的類,直接類名.方法呼叫即可
            L.d("你好,世界")
        }
        R.id.btnToasts -> {

        }
        R.id.btnToastL -> {

        }
        R.id.btnNet -> {

        }
    }
}

點選按鈕之後日誌成功列印

4002920-500f3256d04f9817.png
列印Log.png

AnKo的吐司封裝

這裡介紹AnKo封裝的吐司函式,在build.gradle加入依賴,點選同步

 compile "org.jetbrains.anko:anko-commons:0.10.5"

在按鈕點選事件裡面寫入Anko框架裡的toast短吐司,longToast長吐司函式

override fun onClick(v: View?) {
    when (v?.id) {
        R.id.btnLog -> {
            //加了object關鍵字後成為了單例模式的類,直接類名.方法呼叫即可
            L.d("你好,世界")
        }
        R.id.btnToasts -> {
            toast("短吐司")
        }
        R.id.btnToastL -> {
            longToast("長吐司")
        }
        R.id.btnNet -> {

        }
    }
}

點選執行程式,檢視短吐司和長吐司時候列印成功

空值處理

上一小節頻繁出現了!和 ?兩個符號,這兩個符號在kotlin中代表的是空值處理。

什麼意思呢,我們知道,在我們之前使用java的過程中,很容易就出現了NullPointerException異常。

舉個例子,我們建立一個java學生類

//舉個例子
public class Student {
    public void study() {
        System.out.println("學生在學習");
    }
}

測試Main函式

public class Demo {
    private static Student student;
    public static void main(String[] args) {
        student.study();
    }
}

我們宣告瞭Student物件,但是卻忘記new例項化它,之後就直接呼叫了學生的study方法,執行結果就是空指標異常了。

kotlin對這種現象進行了一些處理,現在我們建立test1.kt,建立主函式,同樣宣告我們的student(kotlin和java的類可以互調),不實現它。

fun main(args: Array<String>) {
    //報錯
    var student: Student= null
}

我們發現程式直接報錯了,這是因為我們的Kotlin預設時不允許你宣告不實現的。但是有些情況,我們是沒法提前實現的,比如要用後面的引數傳遞賦值

這個時候我們可以給該變數的型別加個?,表示允許該變數為空。

var student: Student?= null

我們再輸出學生的學習方法,發現系統再次提示錯誤

4002920-fd65fc2bbcc7ee18.png
空值處理.png

這是因為編譯器檢測到上面我們已經允許student值為空了,如果我們這時候不做任何處理,它仍然可能跑出空指標異常,所以編譯器不允許我們做這麼危險的事情。

移動到錯誤處,提示我們有兩個操作符?.與!!可以操作,我們先使用?.。

//加入以後,即使是空值呼叫study方法也不會丟擲空指標異常
student?.study()

我們發現報錯消失,執行程式,雖然我們沒有例項化Student類就呼叫了study方法,卻沒有任何錯誤,kotlin已經幫我們處理了這個問題,空指標問題解決(因為沒有例項化student變數,當然也沒有任何輸出)。

那!!又是什麼意思,它其實是一個比較作死的符號,如果我們使用它,就表示告訴編譯器,我們不需要kotlin來幫我處理空指標異常了,你跟我像java一樣執行就可以了。

//加入以後,編譯器就不會再幫我們處理空指標異常了
student!!.study()

執行程式,結果果然崩潰了,出現了KotlinNullPointerException異常。所以該符號應該儘量少的使用。

除了上面的兩個操作符外,kotlin還有一個叫做Elvis的 操作符供我們使用。

//加入之後,如果變數不為空,則執行變數的方法,如果變數為空,則執行右邊的操作
student?.study() ?: pritln()
//宣告在主函式之外
fun pritln() {
    println("變數為空")
}

這其實有點類似我們用if去做判斷。

if(student==null){
    print("變數為空啦")
}else{
    student.study()
}

沒錯,正是我們java中對空值進行處理的方式。

完整程式碼。

fun main(args: Array<String>) {
    //報錯
    var student: Student? = null
    //加入以後,即使是空值呼叫方法也不會丟擲空指標異常
//    student?.study()
    //加入以後,編譯器就不會再幫我們處理空指標異常了
//    student!!.study()
    //加入之後,如果變數不為空,則執行變數的方法,如果變數為空,則執行右邊的操作
    student?.study() ?: pritln()
    if(student==null){
        print("變數為空啦")
    }else{
        student.study()
    }
}
//宣告在主函式之外
fun pritln() {
    println("變數為空")
}

本小節就先到這裡啦,如果文章對你有幫助,麻煩點個喜歡 or 關注,謝謝(っ╹◡╹)ノ。

相關文章