天天看點

Kotlin初體驗

距離kotlin成為Android一級開發語言已經一年了,這節将從零開始,實作kotlin的幾個小知識點。

以下操作是在AndroidStudio3.0.1下完成的,如果是3.0以下版本的AndroidStudio,需要

安裝好kotlin插件 才能使用Kotlin進行開發
Kotlin教程推薦 官網文檔 黑馬教程 《Kotlin for android developers》中文版翻譯
相關代碼已經上傳到Github的 KotlinPractice檔案夾 下了

建立項目:

在建立項目中勾選kolin支援後直接下一步即可
Kotlin初體驗

勾選kotlin支援

建立完項目後我們發現主類已經是使用了kotlin代碼了,我們去project的build.gradle目錄下可以看到
ext.kotlin_version = '1.1.51' kotlin  //版本号 
dependencies {
    classpath 'com.android.tools.build:gradle:3.0.1'
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"//依賴
}
           
以及module下build.gradle的:
apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'  
           
實際上這就是我們剛才勾選kotlin後給我們自動生成的,如果我們想要在現有Java代碼項目中使用kotlin,那麼我們就需要手動的去添加這些依賴,或者使用友善的 java代碼轉kotlin 來進行配置,我們看到MainActivity預設已經是kotlin類了
/**
 *  : AppCompatActivity() 
 *  :類名,表示繼承于AppCompatActivity類
 */
class MainActivity : AppCompatActivity() {

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

           

為TextView控件指派:

我們在布局從添加一個TextView,id命名為text_01
<?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"
    tools:context="com.example.administrator.kotlin.MainActivity">

    <TextView
        android:id="@+id/txt_01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="測試文本" />

</LinearLayout>
           
回到Activity,在activity的導包中添加這一行
import kotlinx.android.synthetic.main.activity_main.*
           
它的作用現在隻要知道添加了這一行後我們就不需要再findViewById就可以了,activity_main的意思是Activity布局的包名。
import kotlinx.android.synthetic.main.activity_main.*
/**
 *  : AppCompatActivity() :類名,表示繼承與什麼類
 */
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
//      為TextView設定值,koltin的語句後面是不需要;的,但是如果你加上也不會報錯的
        txt_01.setText("你好,世界")
    }
}
           
運作程式,确實和我們想要的是一樣的

設定按鈕點選事件

我們再為布局添加3個button按鈕
<?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="com.example.administrator.kotlin.MainActivity">

    <TextView
        android:id="@+id/txt_01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="測試文本" />

    
    <Button
        android:id="@+id/btn_01"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" 
        android:text="按鈕1"
        />

    <Button
        android:id="@+id/btn_02"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="按鈕2"
        />

    <Button
        android:id="@+id/btn_03"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="按鈕3"
        />
</LinearLayout>
           
回到Activity,讓MainActivity類繼承于View.OnClickListener接口,我們可以看到koltin繼承接口是使用,号進行的,如果我們想要繼承多個接口,隻需要使用多個,分隔開來就行了
/**
 *  : AppCompatActivity() :類名,表示繼承于什麼類
 *  ,View.OnClickListener, View.OnLongClickListener 表示繼承于 View.OnClickListener 點選事件接口, View.OnLongClickListener 長按事件接口
 */
class MainActivity : AppCompatActivity(), View.OnClickListener, View.OnLongClickListener {


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
//      為TextView設定值,koltin的語句後面是不需要;的,但是如果你加上也不會報錯的
        txt_01.setText("你好,世界")
    }

    /**
     * 重寫OnClickListener接口的onClick方法
     */
    override fun onClick(p0: View?) {
        
    }

    /**
     * 重寫OnLongClickListener接口的onLongClick方法
     */
    override fun onLongClick(p0: View?): Boolean {
        return false
    }

}
           
然後就是我們熟悉的在點選事件裡面使用switch找到對應控件的id了,隻是在kotlin裡面是使用when
/**
 * 重寫OnClickListener接口的onClick方法
 */
override fun onClick(p0: View?) {
    when (p0!!.id) {
        R.id.btn_01 -> {
            Toast.makeText(this, "按鈕1", Toast.LENGTH_LONG).show()
        }

        R.id.btn_02 -> {
            Toast.makeText(this, "按鈕2", Toast.LENGTH_LONG).show()
        }

        R.id.btn_03 -> {
            Toast.makeText(this, "按鈕3", Toast.LENGTH_LONG).show()
        }
    }
}
           
最後要注意,雖然我們通過import kotlinx.android.synthetic.main.activity_main.*使得不需要寫控件的fndId,但是我們仍然是要寫setOnClickListener(this)控件點選回調監聽的

完整代碼:

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Toast

import kotlinx.android.synthetic.main.activity_main.*

/**
 *  : AppCompatActivity() :類名,表示繼承與什麼類
 */
class MainActivity : AppCompatActivity(), View.OnClickListener, View.OnLongClickListener {


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
//      為TextView設定值,koltin的語句後面是不需要;的,但是如果你加上也不會報錯的
        txt_01.setText("你好,世界")
//       設定控件的回調監聽
        init()
    }

    /**
     *  設定控件的回調監聽
     */
    private fun init() {
        btn_01.setOnClickListener(this)
        btn_02.setOnClickListener(this)
        btn_03.setOnClickListener(this)
    }

    /**
     * 重寫OnClickListener接口的onClick方法
     */
    override fun onClick(p0: View?) {
        when (p0!!.id) {
            R.id.btn_01 -> {
                Toast.makeText(this, "按鈕1", Toast.LENGTH_LONG).show()
            }

            R.id.btn_02 -> {
                Toast.makeText(this, "按鈕2", Toast.LENGTH_LONG).show()
            }

            R.id.btn_03 -> {
                Toast.makeText(this, "按鈕3", Toast.LENGTH_LONG).show()
            }
        }
    }

    /**
     * 重寫OnLongClickListener接口的onLongClick方法
     */
    override fun onLongClick(p0: View?): Boolean {
        return false
    }

}
           
運作程式點選按鈕後,出現了我們想要的吐司

實作網絡請求

開始之前我們先在module下配置anko依賴,這是為了等下線程排程用的

module:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'

//    kotlin插件anko
    implementation "org.jetbrains.anko:anko-common:0.10.4"
 

}
           
然後實作我們的network()請求網絡方法,最後不要忘了在AndroidManifest.xml下添加網絡權限
<uses-permission android:name="android.permission.INTERNET" />
           
/**
     * 重寫OnClickListener接口的onClick方法
     */
    override fun onClick(p0: View?) {
        when (p0!!.id) {
            R.id.btn_01 -> {
//              隻進行網絡請求
                network();
            }

            R.id.btn_02 -> {
//              進行網路請求,并且進行json資料解析
                Toast.makeText(this, "按鈕2", Toast.LENGTH_LONG).show()
            }

            R.id.btn_03 -> {
                Toast.makeText(this, "按鈕3", Toast.LENGTH_LONG).show()
            }
        }
    }
           
/**
     * 網絡請求
     */
    private fun network() {
//       聲明要請求的網址,在kotlin中,var能聲明一切類型,而後面的:String其實是可以不加的
        var string: String = "http://www.wanandroid.com/tools/mockapi/2872/k1"
//        作用類似java在子線程中進行網絡請求,但是async在kotlin中叫做協程
        async() {
            val fore = URL(string).readText()
            Log.d("tonjies", fore)
        }

    }
           
觀察日志,我們可以看到确實已經擷取了Json資料
Kotlin初體驗

這裡寫圖檔描述

Json資料解析

接下來我們進行json資料的解析,首先添加gson解析依賴
//    goso解析
    compile "com.google.code.gson:gson:2.4"
           
我們建立bean實體類包,在包下建立解析實體類Student,我們不需要像Java那樣去生成get和set對象,因為這kotlin已經幫我們生成好啦!
/**
 * Created by 舍長 on 2018/4/28.
 * 描述: 資料請求實體類
 */
class Student {
    var name:String?=null
    var age:String?=null
}
           
在按鈕2的點選事件裡面寫一個gson方法,在gson方法裡将網絡請求到的資料轉換成實體類,并且回到UI線程,顯示在文字控件上
/**
     * 重寫OnClickListener接口的onClick方法
     */
    override fun onClick(p0: View?) {
        when (p0!!.id) {
            R.id.btn_01 -> {
//              隻進行網絡請求
                network();
            }

            R.id.btn_02 -> {
//              進行網路請求,并且進行json資料解析
                Toast.makeText(this, "按鈕2", Toast.LENGTH_LONG).show()
                gson();
            }

            R.id.btn_03 -> {
                Toast.makeText(this, "按鈕3", Toast.LENGTH_LONG).show()
            }
        }
    }

    /**
     * 網絡請求并使用gson解析資料
     */
    private fun gson() {
//       聲明要請求的網址,在kotlin中,var能聲明一切類型,而後面的:String其實是可以不加的
        var string: String = "http://www.wanandroid.com/tools/mockapi/2872/student"
//        作用類似java在子線程中進行網絡請求,但是async在kotlin中叫做協程
        async() {
            val fore = URL(string).readText()
            var fromJson: Student = Gson().fromJson(fore, Student::class.java)
//           回到UI線程中去更新資料,這裡的${屬性名}是字元串模闆,作用于Java的+屬性名+相同
            uiThread {
                txt_01.setText("學生的名字是${fromJson.name},年齡是${fromJson.age}")
            }
        }
    }
           
運作程式,點選按鈕二,可以看到文字确實變成了我們想要的json資料:學習的名字是tonjies,年齡是18

這一小節的完整代碼:

布局檔案activity_main:

<?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="com.example.administrator.kotlin.MainActivity">

    <TextView
        android:id="@+id/txt_01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="測試文本" />


    <Button
        android:id="@+id/btn_01"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="按鈕1"
        />

    <Button
        android:id="@+id/btn_02"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="按鈕2"
        />

    <Button
        android:id="@+id/btn_03"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="按鈕3"
        />
</LinearLayout>

           
MainActivity
package com.example.administrator.kotlin

import android.icu.lang.UCharacter.GraphemeClusterBreak.L
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Toast
import com.example.administrator.kotlin.R.id.async
import com.example.administrator.kotlin.bean.Student
import com.google.gson.Gson

import kotlinx.android.synthetic.main.activity_main.*
import java.net.URL
import org.jetbrains.anko.custom.async
import org.jetbrains.anko.uiThread

/**
 *  : AppCompatActivity() :類名,表示繼承與什麼類
 */
class MainActivity : AppCompatActivity(), View.OnClickListener, View.OnLongClickListener {


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
//      為TextView設定值,koltin的語句後面是不需要;的,但是如果你加上也不會報錯的
        txt_01.setText("你好,世界")
//       設定控件的回調監聽
        init()
    }

    /**
     *  設定控件的回調監聽
     */
    private fun init() {
        btn_01.setOnClickListener(this)
        btn_02.setOnClickListener(this)
        btn_03.setOnClickListener(this)
    }

    /**
     * 重寫OnClickListener接口的onClick方法
     */
    override fun onClick(p0: View?) {
        when (p0!!.id) {
            R.id.btn_01 -> {
//              隻進行網絡請求
                network();
            }

            R.id.btn_02 -> {
//              進行網路請求,并且進行json資料解析
                Toast.makeText(this, "按鈕2", Toast.LENGTH_LONG).show()
                gson();
            }

            R.id.btn_03 -> {
                Toast.makeText(this, "按鈕3", Toast.LENGTH_LONG).show()
            }
        }
    }

    /**
     * 網絡請求并使用gson解析資料
     */
    private fun gson() {
//       聲明要請求的網址,在kotlin中,var能聲明一切類型,而後面的:String其實是可以不加的
        var string: String = "http://www.wanandroid.com/tools/mockapi/2872/student"
//        作用類似java在子線程中進行網絡請求,但是async在kotlin中叫做協程
        async() {
            val fore = URL(string).readText()
            var fromJson: Student = Gson().fromJson(fore, Student::class.java)
//           回到UI線程中去更新資料,這裡的${屬性名}是字元串模闆,作用于Java的+屬性名+相同
            uiThread {
                txt_01.setText("學生的名字是${fromJson.name},年齡是${fromJson.age}")
            }
        }
    }

    /**
     * 網絡請求
     */
    private fun network() {
//       聲明要請求的網址,在kotlin中,var能聲明一切類型,而後面的:String其實是可以不加的
        var string: String = "http://www.wanandroid.com/tools/mockapi/2872/student"
//        作用類似java在子線程中進行網絡請求,但是async在kotlin中叫做協程
        async() {
            val fore = URL(string).readText()
            Log.d("tonjies", fore)
        }

    }

    /**
     * 重寫OnLongClickListener接口的onLongClick方法
     */
    override fun onLongClick(p0: View?): Boolean {
        return false
    }

}

           
好了,這一小節就到這裡啦!在學習的過程中,參考開源項目和巧妙使用 Java代碼轉kotlin 的快捷鍵是挺有用的