極簡Kotlin-For-Android(一)

安裝 Kotlin 插件java

Android Studio 3.+ 已經有了 Kotlin 插件,若是是更早的版本,點擊 Android Studio | File | Settings | Plugins,搜索 Kotlin ,安裝,重啓 Android Studio .數據庫

建立工程編程

點擊 Android Studio | File | New project : 勾選Incloud Kotlin support.
就會看到下面的類:json

class MainActivity : AppCompatActivity() {

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

定義類api

1.只需使用class關鍵字.
2.它有一個惟一默認的構造器,大部分狀況下只需使用這個默認構造器便可.
3.構造函數的函數體,寫在init塊{}中數組

class Person(name:String ,age : Int) {
    init {
    }
}
複製代碼

類繼承安全

1.上帝類是Any(相似於java中的Object)
2.全部類默認是不可繼承的(final),咱們只能繼承聲明open或abstract的類bash

open class Animal(name: String)
class Person(name:String ,age : Int) : Animal(name) 
複製代碼

函數(java中的方法)網絡

1.使用fun關鍵字
2.若是沒有指定返回值,默認返回Unit(java中的void),固然也能夠指定返回任何類型app

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<String>) : RecyclerView.Adapter<ForecastListAdapter.ViewHolder>(){
    //綁定數據
    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<String>(
            "北京 -0 - 微風",
            "北京 -10 - 微風",
            "北京 -13 - 微風",
            "北京 -20 - 微風",
            "北京 -5 - 微風"
            )
recycler.adapter = ForecastListAdapter(weaList)
複製代碼

關於List的建立:
能夠經過一個函數listOf建立一個常亮list,它接收任何類型的vararg(可變長度參數).還有不少其餘函數:setOf,arrayListOf hashSetOf, etc...

運行你的項目吧:

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

變量和屬性
在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<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 咱們都是作夢的夢想家

相關文章
相關標籤/搜索