極簡Kotlin-For-Android(一)

收藏待读

極簡Kotlin-For-Android(一)

安裝 Kotlin 插件

Android Studio 3.+ 已經有了 Kotlin 插件,如果是更早的版本,點擊 Android Studio | File | Settings | Plugins,搜索 Kotlin ,安裝,重啟 Android Studio .

創建工程

點擊 Android Studio | File | New project : 勾選Incloud Kotlin support.

就會看到下面的類:

class MainActivity : AppCompatActivity() {

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

定義類

1.只需使用class關鍵字.

2.它有一個唯一默認的構造器,大部分情況下只需使用這個默認構造器即可.

3.構造函數的函數體,寫在init塊{}中

class Person(name:String ,age : Int) {
    init {
    }
}

類繼承

1.上帝類是Any(類似於java中的Object)

2.所有類默認是不可繼承的(final),我們只能繼承聲明open或abstract的類

open class Animal(name: String)
class Person(name:String ,age : Int) : Animal(name)

函數(java中的方法)

1.使用fun關鍵字

2.如果沒有指定返回值,默認返回Unit(java中的void),當然也可以指定返回任何類型

fun add(age1:Int ,age2:Int) : Int{
    return age1+age2
}

Tips:分號不是必須的,結尾不使用分號會節約很多時間,養成這個好習慣吧!

3.如果返回結果可以使用表達式表達出來,直接使用等號:

fun add2(age1: Int , age2: Int) : Int = age1+age2
構造方法和函數參數

1.kotlin中參數是先寫名稱,後寫類型….(有點不適應)

2.可以給參數一個指定默認值,使其變得可選,例如下面toast函數第二個參數給了默認值,調用時候可以不傳第二個值(java中重載方法的替換?)

fun toast(msg : String , length : Int = Toast.LENGTH_LONG){
    Toast.makeText(this,msg,length).show();
}

toast("打印吐司鴨")
toast("打印吐司鴨",Toast.LENGTH_SHORT)

Tips:

String模板內插*:

val name = "susan"
println("name : $name")
輸出結果: name : susan

編寫你的第一個類

我們在MainActivity的布局文件中加入RecyclerView,然後設置好LayoutManager:

val recycler = findViewById(R.id.recycler) as RecyclerView
recycler.layoutManager = LinearLayoutManager(this)

如上代碼,LayoutManager會通過屬性設置,而不是通過set方法.

對象實例化也去掉了new關鍵字,構造函數仍然會被調用.

接着設置Adapter:

class ForecastListAdapter(val items : List) : RecyclerView.Adapter(){
    //綁定數據
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.textView.text = items[position]
    }
    //返回list count
    override fun getItemCount(): Int {
        return items.size
    }
    //創建viewHolder
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(TextView(parent.context))
    }
    class ViewHolder(val textView : TextView) : RecyclerView.ViewHolder(textView)
}

回到MainActivity,現在我們將少量數據放入recyclerview中:

//定義天氣數組數組
    val weaList= listOf(
            "北京 -0 -  微風",
            "北京 -10 - 微風",
            "北京 -13 - 微風",
            "北京 -20 - 微風",
            "北京 -5 -  微風"
            )
recycler.adapter = ForecastListAdapter(weaList)

關於List的創建:

可以通過一個函數listOf創建一個常亮list,它接收任何類型的vararg(可變長度參數).還有很多其他函數:setOf,arrayListOf hashSetOf, etc…

運行你的項目吧:

極簡Kotlin-For-Android(一)

image

接下來,必須要學習一些基本類型,變量,屬性等才能繼續.

變量和屬性在kotlin中,一切都是對象~

基本類型integer float boolean等類型依然存在,不過是以對象存在.它們的工作方式與java十分相似,需要注意以下幾點:

數字類型不會自動轉型.例如不能給Double分配int型值

val i: Int = 7
    val d: Double = i.toDouble()

char不能直接作為一個數字來處理,需要轉換成數字

val a : Char = 'c'
    val b : Int = a.toInt()

位運算 java中使用的 || 或者 && kotlin中使用and or

val willOr = FLAG1 or FLAG2
    val willAnd = FLAG1 and FLAG2

字面可以寫明具體的類型,但是不是必須的,編譯器會自動解析類型

val i = 12 //as Int
val l = 3l //as Long
val f = 5f //as Float
val d = 3.5 //as Double

一個String 可以像數組那樣訪問,並且被迭代

val s = "test"
val t = s[2]//一個字符's'
//迭代
val o = "test"
for (b in o){
    print(t)
}

變量變量可簡單定義為 : val(不可變)和var(可變).但是不可變在kotlin是一個很重要的概念.

一個不可變對象意味着它在實例化之後就不能再去改變它的狀態了。如果你需要一個這個對象修改之後的版本,那就會再創建一個新的對象。這個讓編程更加具有健壯性和預估性。

Java中,大部分的對象是可變的,那就意味着任何可以訪問它這個對象的代碼都可以去修改它,從而影響整個程序的其它地方。不可變對象也可以說是線程安全的,因為它們無法去改變,也不需要去定義訪問控制,因為所有線程訪問到的對象都是同一個

一個重要的概念是:儘可能地使用val。除了個別情況(特別是在Android中,有很多類我們是不會去直接調用構造函數的),大多數時候是可以的。

如果我們需要使用更多的范型類型,則需要指定:

val a: Any = 23
val c: Context = activity

屬性沒有任何指定,屬性會默認使用getter和setter.

class Dog {
    val color : Int = 0
}

當然也可以自定義set,get.

var color : Int = 3
    get() = field.toBigDecimal().intValueExact()
    set(value) {
        field = 3 + value
    }

Anko來了

  • 主要目的是用來替換之前XMl的方式來使用代碼生成UI布局
  • Anko還包含了許多有幫助的函數和屬性來避免寫很多代碼
  • 了解Anko的實現方式對學習kotlin有很大幫組

開始使用Anko剛使用findviewbyid的可以用fins替換

val recycler : RecyclerView  = find(R.id.recycler)

Anko還有一些別的實用功能:

實例化Intent,Activity之間的跳轉,Fragment的創建,數據庫的訪問,Alert的創建……。

擴展函數

擴展函數數是指在一個類上增加一種新的行為,甚至我們沒有這個類代碼的訪問權限。這是一個在缺少有用函數的類上擴展的方法。

在Java中,通常會實現很多帶有static方法的工具類。Kotlin中擴展函數的一個優勢是我們不需要在調用方法的時候把整個對象當作參數傳入。擴展函數表現得就像是屬於這個類的一樣,而且我們可以使用this關鍵字和調用所有public方法。

舉個例子,我們可以創建一個toast函數,這個函數不需要傳入任何context,它可以被任何Context或者它的子類調用,比如Activity或者Service:

fun Context.toast(message: CharSequence, duration: Int = Toast.LENGTH_SHORT) {    
    Toast.makeText(this, message, duration).show()
}

這個方法可以在Activity內部直接調用:

toast("Hello world!")
toast("Hello world!", Toast.LENGTH_LONG)

擴展函數並不是真正地修改了原來的類,它是以靜態導入的方式來實現的。擴展函數可以被聲明在任何文件中,因此有個通用的實踐是把一系列有關的函數放在一個新建的文件里。

執行一個請求如果只是執行一個簡單的api請求,我們可以不用任何非三方庫實現

class Request(val url : String) {
    fun run(){
        val jsonStr = URL(url).readText()
        Log.d("result",jsonStr)
    }
}

眾所周知,在子線程中是不允許進行網絡請求的,java的AsyncTask是非常醜陋的…diss一波…

Anko提供了非常簡單的DSL來處理異步任務,它滿足大部分的需求。它提供了一個基本的async函數用於在其它線程執行代碼,也可以選擇通過調用uiThread的方式回到主線程。在子線程中執行請求如下這麼簡單:

val url = "https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22"
        doAsync() {
            Request(url).run()
            uiThread { toast("Request") }
        }

此時運行項目,查看log,可以發現一個簡單請求已經實現了!

接着我們要把他使用json解析,轉換成實體類.

數據類

數據類是一種非常強大的類,它可以讓你避免創建Java中的用於保存狀態但又操作非常簡單的POJO的模版代碼。它們通常只提供了用於訪問它們屬性的簡單的getter和setter。定義一個新的數據類非常簡單:

data class Forecast(val date : Date , val temp : Float ,
                    val details : String)

轉換json到數據類

關於伴生對象Companion objects :

Kotlin允許我們去定義一些行為與靜態對象一樣的對象。儘管這些對象可以用眾所周知的模式來實現,比如容易實現的單例模式。我們需要一個類裏面有一些靜態的屬性、常量或者函數,我們可以使用companion object。這個對象被這個類的所有對象所共享,就像Java中的靜態屬性或者方法。

修改一下Request類:

class Request(val zipCode : String) {

    companion object {
        private val APP_ID = "15646a06818f61f7b8d7823ca833e1ce"
        private val URL = "http://api.openweathermap.org/data/2.5/" +"forecast/daily?mode=json&units=metric&cnt=7"
        private val COMPLETE_URL = "$URL&APPID=$APP_ID&q="
    }

    public fun execute() : ForecastResult{
        val jsonStr = URL(COMPLETE_URL + zipCode).readText()
        return Gson().fromJson(jsonStr,ForecastResult::class.java)
    }

    @Deprecated("使用execute替換")
    public fun run(){
        val jsonStr = URL(url).readText()
        Log.d("result",jsonStr)
    }
}

數據類:

data class ForecastResult(val city: ResponseClasses.City,
                     val cnt: Int,
                     val cod: String,
                     val list: List,
                     val message: Double) {


    data class ForeCast(
            val clouds: Int,
            val deg: Int,
            val dt: Int,
            val humidity: Int,
            val pressure: Double,
            val rain: Double,
            val speed: Double,
            val temp: Temp,
            val weather: List
    )

    data class Temp(
            val day: Double,
            val eve: Double,
            val max: Double,
            val min: Double,
            val morn: Double,
            val night: Double
    )

    data class Weather(
            val description: String,
            val icon: String,
            val id: Int,
            val main: String
    )

    data class City(
            val coord: Coord,
            val country: String,
            val id: Int,
            val name: String,
            val population: Int
    )

    data class Coord(
            val lat: Double,
            val lon: Double
    )
}

好累,先寫到這裡@[email protected]

分享一首好音樂:
Lo Que Siento – cuco
我們都是做夢的夢想家

原文 : 簡書

相關閱讀

免责声明:本文内容来源于簡書,已注明原文出处和链接,文章观点不代表立场,如若侵犯到您的权益,或涉不实谣言,敬请向我们提出检举。