極簡Kotlin-For-Android(一)

安裝 Kotlin 插件

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

創(chuàng)建工程

點擊 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關(guān)鍵字.
2.它有一個唯一默認(rèn)的構(gòu)造器,大部分情況下只需使用這個默認(rèn)構(gòu)造器即可.
3.構(gòu)造函數(shù)的函數(shù)體,寫在init塊{}中

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

類繼承

1.上帝類是Any(類似于java中的Object)
2.所有類默認(rèn)是不可繼承的(final),我們只能繼承聲明open或abstract的類

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

函數(shù)(java中的方法)

1.使用fun關(guān)鍵字
2.如果沒有指定返回值,默認(rèn)返回Unit(java中的void),當(dāng)然也可以指定返回任何類型

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

Tips: 分號不是必須的,結(jié)尾不使用分號會節(jié)約很多時間,養(yǎng)成這個好習(xí)慣吧!

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

fun add2(age1: Int , age2: Int) : Int = age1+age2

構(gòu)造方法和函數(shù)參數(shù)
1.kotlin中參數(shù)是先寫名稱,后寫類型....(有點不適應(yīng))
2.可以給參數(shù)一個指定默認(rèn)值,使其變得可選,例如下面toast函數(shù)第二個參數(shù)給了默認(rèn)值,調(diào)用時候可以不傳第二個值(java中重載方法的替換?)

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

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

Tips:
String模板內(nèi)插*:

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

編寫你的第一個類

我們在MainActivity的布局文件中加入RecyclerView,然后設(shè)置好LayoutManager:

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

如上代碼,LayoutManager會通過屬性設(shè)置,而不是通過set方法.
對象實例化也去掉了new關(guān)鍵字,構(gòu)造函數(shù)仍然會被調(diào)用.
接著設(shè)置Adapter:

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

回到MainActivity,現(xiàn)在我們將少量數(shù)據(jù)放入recyclerview中:

    //定義天氣數(shù)組數(shù)組
    val weaList= listOf<String>(
            "北京 -0 -  微風(fēng)",
            "北京 -10 - 微風(fēng)",
            "北京 -13 - 微風(fēng)",
            "北京 -20 - 微風(fēng)",
            "北京 -5 -  微風(fēng)"
            )
recycler.adapter = ForecastListAdapter(weaList)

關(guān)于List的創(chuàng)建:
可以通過一個函數(shù)listOf創(chuàng)建一個常亮list,它接收任何類型的vararg(可變長度參數(shù)).還有很多其他函數(shù):setOf,arrayListOf hashSetOf, etc...

運行你的項目吧:

image

接下來,必須要學(xué)習(xí)一些基本類型,變量,屬性等才能繼續(xù).

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

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

數(shù)字類型不會自動轉(zhuǎn)型.例如不能給Double分配int型值

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

char不能直接作為一個數(shù)字來處理,需要轉(zhuǎn)換成數(shù)字

    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 可以像數(shù)組那樣訪問,并且被迭代

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

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

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

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

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

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

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

屬性
沒有任何指定,屬性會默認(rèn)使用getter和setter.

class Dog {
    val color : Int = 0
}

當(dāng)然也可以自定義set,get.

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

Anko來了

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

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

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

Anko還有一些別的實用功能:
實例化Intent,Activity之間的跳轉(zhuǎn),F(xiàn)ragment的創(chuàng)建,數(shù)據(jù)庫的訪問,Alert的創(chuàng)建......。

擴展函數(shù)

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

在Java中,通常會實現(xiàn)很多帶有static方法的工具類。Kotlin中擴展函數(shù)的一個優(yōu)勢是我們不需要在調(diào)用方法的時候把整個對象當(dāng)作參數(shù)傳入。擴展函數(shù)表現(xiàn)得就像是屬于這個類的一樣,而且我們可以使用this關(guān)鍵字和調(diào)用所有public方法。

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

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

這個方法可以在Activity內(nèi)部直接調(diào)用:

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

擴展函數(shù)并不是真正地修改了原來的類,它是以靜態(tài)導(dǎo)入的方式來實現(xiàn)的。擴展函數(shù)可以被聲明在任何文件中,因此有個通用的實踐是把一系列有關(guān)的函數(shù)放在一個新建的文件里。

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

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

眾所周知,在子線程中是不允許進行網(wǎng)絡(luò)請求的,java的AsyncTask是非常丑陋的...diss一波...

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

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

此時運行項目,查看log,可以發(fā)現(xiàn)一個簡單請求已經(jīng)實現(xiàn)了!
接著我們要把他使用json解析,轉(zhuǎn)換成實體類.

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

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

轉(zhuǎn)換json到數(shù)據(jù)類

關(guān)于伴生對象Companion objects :
Kotlin允許我們?nèi)ザx一些行為與靜態(tài)對象一樣的對象。盡管這些對象可以用眾所周知的模式來實現(xiàn),比如容易實現(xiàn)的單例模式。我們需要一個類里面有一些靜態(tài)的屬性、常量或者函數(shù),我們可以使用companion object。這個對象被這個類的所有對象所共享,就像Java中的靜態(tài)屬性或者方法。

修改一下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)
    }
}

數(shù)據(jù)類:

data class ForecastResult(val city: ResponseClasses.City,
                     val cnt: Int,
                     val cod: String,
                     val list: List<ResponseClasses.ForeCast>,
                     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<Weather>
    )

    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
    )
}

好累,先寫到這里@_@

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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容