1. 程式人生 > >Android知識體系梳理筆記五:Kotlin學習筆記一:類和繼承以及Anko(全)的基本使用

Android知識體系梳理筆記五:Kotlin學習筆記一:類和繼承以及Anko(全)的基本使用

前言

對於kotlin,我是邊寫專案邊學的方式來學習的,這些都是在做專案的時候遇到的問題及擴充套件學習的時候記錄的,雖然有些內容不會涉及,但是我認為這種邊寫程式碼邊學習的方式特別有助於記憶,畢竟紙上得來終覺淺!

類和繼承

Kotlin較Java在繼承和實現上面簡便了很多;Java在繼承上要extend,實現介面要implement,
而Kotlin加個“:”就行了,之後的類和介面用逗號隔開

abstract class BaseActivity() : RxAppCompatActivity() ,IBaseView

構造:Kotlin有主構造和次構造之分

  1. 主構造申明在類名的後面,若這個主構造被可見性修飾符或註解修飾,則這個主構造無法省略constructor修飾符
//無法省略constructor
class Customer public @Inject constructor(name: String) { ... }

...
//可以省略constructor
class Customer(name: String){}

在這個主建構函式中無法寫初始化程式碼,但可以宣告屬性(屬性可以有預設值,當然也可以在類體內初始化宣告),而屬性的初始化程式碼可以放到init()程式碼塊裡,而且在init程式碼塊裡可以使用在主構造裡宣告的屬性。

class Customer(name: String) {
    init {
        val customerKey = name.toUpperCase()
} }

次構造:類也可以宣告字首有 constructor 的次建構函式

class Person {
    constructor(parent: Person) {
        parent.children.add(this)
    }
}

如果類有一個主建構函式,每個次建構函式需要委託給主建構函式, 可以直接委託或者通過別的次建構函式間接委託。委託到同一個類的另一個建構函式 用 this 關鍵字即可:

class Person(val name: String) {
    constructor(name: String, parent: Person
)
: this(name) { parent.children.add(this) } }

如果一個非抽象類沒有宣告任何(主或次)建構函式,它會有一個生成的 不帶引數的主建構函式。建構函式的可見性是 public。如果你不希望你的類 有一個公有建構函式,你需要宣告一個帶有非預設可見性的空的主建構函式:

class DontCreateMe private constructor () {
}

PS1 :在 JVM 上,如果主建構函式的所有的引數都有預設值,編譯器會生成 一個額外的無參建構函式,它將使用預設值。這使得 Kotlin 更易於使用像 Jackson 或者 JPA 這樣的通過無參建構函式建立類的例項的庫。

class Customer(val customerName: String = "")
  • 建立例項物件
    1. Kotlin裡沒有new關鍵字,so我們可以直接Customer()來例項化物件
val invoice = Invoice()

val customer = Customer("Joe Smith")
  • 繼承
    1. 如果該類有一個主建構函式,其基型別可以(並且必須) 用(基型別的)主建構函式引數就地初始化。
      如果類沒有主建構函式,那麼每個次建構函式必須 使用 super{:.keyword} 關鍵字初始化其基型別,或委託給另一個建構函式做到這一點。 注意,在這種情況下,不同的次建構函式可以呼叫基型別的不同的建構函式:
class MyView : View {
    constructor(ctx: Context) : super(ctx) {
    }

    constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs) {
    }
}

而在Java程式碼裡我們自定義View,我們初始化構造會經常這樣做

public class EmptyErrLayout extends FrameLayout {

    public EmptyErrLayout(Context context) {
        this(context, null);
    }

    public EmptyErrLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
        init(attrs);
    }
    ...
}

而在Kotlin裡可以這樣做

    constructor(context: Context):this (context,null){

    }

    constructor(context: Context,atts: AttributeSet?) : super (context,atts){
        init(context,atts)
    }

也可以

//這裡初始化了3個建構函式
class EmptyErrLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = -1) : FrameLayout(context, attrs, defStyleAttr) {...}

@JvmOverloads:表示如果一個方法有N個引數,其中M個具有預設值,則會產生M個過載:第一個採用N-1個引數(除了最後一個引數之外的所有引數),第二個採用N-2個引數,同上。就像上面的例子,構造裡有3個引數,有兩個引數具有預設值(attrs: AttributeSet? = null, defStyleAttr: Int = -1),所以會產生這個建構函式的2個過載
* 覆蓋規則

覆蓋方法需要用到override關鍵字

open class Base {
  open fun v() {}
  fun nv() {}
}
class Derived() : Base() {
//Derived的子類可以再次覆蓋
  override fun v() {}
  //final override fun v() {},表示子類禁止再次覆蓋
}

在 Kotlin 中,實現繼承由下述規則規定:如果一個類從它的直接超類繼承相同成員的多個實現, 它必須覆蓋這個成員並提供其自己的實現(也許用繼承來的其中之一)。 為了表示採用從哪個超型別繼承的實現,我們使用由尖括號中超型別名限定的 super,如 super:

open class A {
  open fun f() { print("A") }
  fun a() { print("a") }
}

interface B {
  fun f() { print("B") } // 介面成員預設就是 'open' 的
  fun b() { print("b") }
}

class C() : A(), B {
  // 編譯器要求覆蓋 f():
  override fun f() {
    super<A>.f() // 呼叫 A.f()
    super<B>.f() // 呼叫 B.f()
  }
}

重寫屬性以類似於覆蓋方法的方式工作。注意,可以在主建構函式中使用override關鍵字作為屬性宣告的一部分

open class Foo {
    open val x: Int get { ... }
}

class Bar1(override val x: Int) : Foo() {

}
  • 抽象類:類和其中的某些成員可以宣告為 abstract,可以用一個抽象成員覆蓋一個非抽象的開放成員
open class Base {
  open fun f() {}
}

abstract class Derived : Base() {
  override abstract fun f()
}
  • 密封類:密封類用來表示受限的類層次結構:當一個值為有限集中的 型別、而不能有任何其他型別時。在某種意義上,他們是列舉類的擴充套件:列舉型別的值集合 也是受限的,但每個列舉常量只存在一個例項,而密封類 的一個子類可以有可包含狀態的多個例項。
//要宣告一個密封類,需要在類名前面新增 sealed 修飾符。雖然密封類也可以 有子類,但是所以子類宣告都必須巢狀在這個密封類宣告內部。
sealed class Expr {
    class Const(val number: Double) : Expr()
    class Sum(val e1: Expr, val e2: Expr) : Expr()
    object NotANumber : Expr()
}

Anko

Anko is a Kotlin library which makes Android application development faster and easier. It makes your code clean and easy to read, and lets you forget about rough edges of the Android SDK for Java.

Anko是能使Android開發更快更容易的一個Kotlin庫,是你的程式碼清潔並且易讀,能讓人忘掉Android SDK for Java時的粗糙不友好

使用

//使用Anko所有的元件庫,包括commons,layouts,sqlite,coroutiness
dependencies {
    compile "org.jetbrains.anko:anko:$anko_version"
}
//也可以只用其中一部分,新增想要使用的那一部分依賴
dependencies {
    // Anko Commons
    compile "org.jetbrains.anko:anko-commons:$anko_version"

    // Anko Layouts
    compile "org.jetbrains.anko:anko-sdk25:$anko_version" // sdk15, sdk19, sdk21, sdk23 are also available
    compile "org.jetbrains.anko:anko-appcompat-v7:$anko_version"

    // Coroutine listeners for Anko Layouts
    compile "org.jetbrains.anko:anko-sdk25-coroutines:$anko_version"
    compile "org.jetbrains.anko:anko-appcompat-v7-coroutines:$anko_version"

    // Anko SQLite
    compile "org.jetbrains.anko:anko-sqlite:$anko_version"
}

組成

  • Anko Commons: 一個用於Intent意圖,對話方塊,列印等方面的輕量級安全庫
  • Anko Layouts: 一種快速和安全的方式來編寫動態Android佈局
  • Anko SQLite:針對Android SQLite的查詢DSL和解析器集合;
  • Anko Coroutines:基於kotlinx.corutines庫的實用程式。

Anko Commons

(1) intent

  • 原始的意圖跳轉需要4至5行程式碼左右
val intent = Intent(this, SomeOtherActivity::class.java)
intent.putExtra("id", 5)
intent.setFlag(Intent.FLAG_ACTIVITY_SINGLE_TOP)
startActivity(intent)
  • 而使用Anko以後只需要一行就可以搞定
//若沒有開啟Flag,直接把.singleTop()去掉就行,更加簡單
startActivity(intentFor<SomeOtherActivity>("id" to 5).singleTop())

(2) dialogs:使用還需新增以下依賴

// Anko Layouts
    compile "org.jetbrains.anko:anko-sdk25:$anko_version" // sdk15, sdk19, sdk21, sdk23 are also available
  • toast使用
toast("Hi there!")
toast(R.string.message)
longToast("Wow, such a duration")
  • 普通的對話方塊
alert("Hi, I'm Roy", "Have you tried turning it off and on again?") {
    yesButton { toast("Oh…") }
    noButton {}
}.show()
  • appcompat中的Dialogs
//這是Activity中的方法
alert(Appcompat, "Some text message").show()
//Fagment中使用
activity.alert(Appcompat, "Some text message").show()
  • 自定義dialog
alert {
    customView {

        editText()//自定義佈局
        //也可以這樣
        var  view = View.inflate(mContext,R.layout.fragment_news_main_layout,null)
        addView(view,ViewGroup.LayoutParams(100,100))
    }
}.show()
  • 選擇對話方塊
 val countries = listOf("Russia", "USA", "Japan", "Australia")
            selector("Where are you from?", countries, { dialogInterface, i ->
                toast("So you're living in ${countries[i]}, right?")
            })
  • 進度對話方塊
val dialog = progressDialog(message = "Please wait a bit…", title = "Fetching data")

(3) log

class SomeActivity : Activity(), AnkoLogger {
    private fun someMethod() {
        info("London is the capital of Great Britain")
        debug(5) // .toString() method will be executed
        warn(null) // "null" will be printed
    }
}

(4) 佈局相關
* anko能簡便地進行dip,sp設定和px-dip,sp之間的轉換

        button.sp(16)
        button.dip(26)
        button.px2dip(20)
        button.px2sp(80)
  • applyRecursively():如果佈局是一個ViewGroup,裡面有幾個相同的子view,此方法可以迭代對子View進行設定
verticalLayout {
    editText {
        hint = "Name"
    }
    editText {
        hint = "Password"
    }
}.applyRecursively { view -> when(view) {
    is EditText -> view.textSize = 20f
}}

Anko Layouts

(1).預設情況下,Android中的UI是使用XML編寫的。這在以下方面是不方便的:

  • 這不是安全的;
  • 它不是無效的;
  • 它迫使您為每個佈局編寫幾乎相同的程式碼 ;
  • 在裝置上解析XML浪費CPU時間和電池;
  • 最重要的是,它不允許程式碼重用。

(2) DSL動態佈局

DSL使同樣的程式碼佈局邏輯較於之前的程式碼佈局邏輯容易閱讀,易於編寫,並且沒有執行時開銷

verticalLayout {
    val name = editText()
    button("Say Hello") {
        onClick { toast("Hello, ${name.text}!") }
    }
}

(3) AnkoComponent:使用提供的AnkoComponent介面,您還可以免費獲得DSL 佈局預覽功能。

配合Anko Support外掛可以在IDE佈局視窗中預覽用anko程式碼寫的佈局

class MyActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
        super.onCreate(savedInstanceState, persistentState)
        MyActivityUI().setContentView(this)
    }
}

class MyActivityUI : AnkoComponent<MyActivity> {
    override fun createView(ui: AnkoContext<MyActivity>) = ui.apply {
        verticalLayout {
            val name = editText()
            button("Say Hello") {
                onClick { ctx.toast("Hello, ${name.text}!") }
            }
        }
    }.view
}

將游標放在MyActivityUI宣告內的某個地方,開啟Anko Layout Preview工具視窗(“View”→“Tool Windows”→“Anko Layout Preview”),然後按重新整理。

這需要構建專案,所以在影象實際顯示之前可能需要一些時間。

該外掛還支援將佈局從XML格式轉換為Anko Layouts程式碼。開啟一個XML檔案並選擇“程式碼”→“轉換為安科佈局DSL”。您可以同時轉換多個XML佈局檔案。

(4) 包含標籤:很容易將XML佈局插入到DSL中。使用include()功能

include<View>(R.layout.something) {
    backgroundColor = Color.RED
}.lparams(width = matchParent) { margin = dip(12) }

(5) 介面監聽:

在Java中

button.setOnClickListener(object : OnClickListener {
    override fun onClick(v: View) {
        launch(UI) {
            val user = myRetrofitService.getUser().await()
            showUser(user)
        }
    }
})

使用Kotlin及Anko

button("Login") {
    onClick {
        val user = myRetrofitService.getUser().await()
        showUser(user)
    }
}

在kotlin中一個監聽有很多方法而沒使用anko,程式碼會是這樣

seekBar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
    override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
        // Something
    }
    override fun onStartTrackingTouch(seekBar: SeekBar?) {
        // Just an empty method
    }
    override fun onStopTrackingTouch(seekBar: SeekBar) {
        // Another empty method
    }
})

而使用Anko

seekBar {
    onSeekBarChangeListener {
        onProgressChanged { seekBar, progress, fromUser ->
            // Something
        }
    }
}

(6) Layouts and LayoutParams

在xml裡寫佈局

<ImageView 
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="5dip"
    android:layout_marginTop="10dip"
    android:src="@drawable/something" />

在anko中,LayoutParams可以在View描述之後指定lparams():如果指定lparams(),但省略width和/或height,它們的預設值都是wrapContent。

例舉一些屬性:(linearLayout的屬性,各佈局不同)

  • horizontalMargin 設定左右邊距,
  • verticalMargin 設定頂部和底部,
  • margin 同時設定所有四個邊距。
linearLayout {
    button("Login") {
        textSize = 26f
    }.lparams(width = wrapContent) {
        horizontalMargin = dip(5)
        topMargin = dip(10)
    }
}

(7) 助手塊:如果您不需要為某些View設定任何屬性,則可以省略{}並寫入button(“Ok”),甚至只是button():

verticalLayout {
    button("Ok")
    button(R.string.cancel)
}

(8) 主題塊:可以很方便的設定view的屬性

verticalLayout {
    themedButton("Ok", theme = R.style.myTheme)
}

Anko SQLite

Anko提供了大量的擴充套件功能,以簡化與SQLite資料庫的工作,在專案中我還是會選擇第三方資料庫,這裡就跳過了,想看的請移步AnkoSQlite

Anko Coroutines:有兩個比較有用的方法

  • asReference():非同步獲取例項Activity或Fragment可能會導致記憶體洩漏。
    asReference()在這種情況下使用:
suspend fun getData(): Data { ... }

class MyActivity : Activity() {
    fun loadAndShowData() {
    // Ref<T> uses the WeakReference under the hood
    val ref: Ref<MyActivity> = this.asReference()

    async(UI) {
        val data = getData()

        // Use ref() instead of [email protected]
        ref().showData()
    }
    }

    fun showData(data: Data) { ... }
}
  • bg():可以使用bg()在後臺執行緒上輕鬆執行程式碼:
fun getData(): Data { ... }
fun showData(data: Data) { ... }

async(UI) {
    val data: Deferred<Data> = bg {
    // Runs in background
    getData()
    }

    // This code is executed on the UI thread
    showData(data.await())
}

Github(剛開始寫,主要是把以前推薦的專案改成Kotlin版的)

拼搏在技術道路上的一隻小白And成長之路

相關推薦

Android知識體系梳理筆記Kotlin學習筆記繼承以及Anko基本使用

前言 對於kotlin,我是邊寫專案邊學的方式來學習的,這些都是在做專案的時候遇到的問題及擴充套件學習的時候記錄的,雖然有些內容不會涉及,但是我認為這種邊寫程式碼邊學習的方式特別有助於記憶,畢竟紙上得來終覺淺! 類和繼承 Kotlin較Java在繼承和實現

Android知識體系梳理筆記AIDL進階之Binder機制

為什麼學習Binder機制 Binder是Android系統中最重要的特性之一;正如其名“粘合劑”所喻,它是系統間各個元件的橋樑,Android系統的開放式設計也很大程度上得益於這種及其方便的跨程序通訊機制。 Binder是一種程序間通訊機制,能幫助我們進行

Kotlin學習歷程Kotlin開發安卓的初體驗

1.告別findViewById 不同於 JAVA 中,在 Kotlin 中 findViewById 本身就簡化了很多,這得益於 Kotlin 的型別推斷以及轉型語法後置: val onlyTv = findViewById(R.id.onlyTv) as TextVi

Kotlin學習之旅(D3)-繼承

Day 3 Kotlin學習之旅-第三天 今天的主題是:類與繼承 前言 今日目標 今天空閒的時候 baidu一下,發現簡書,掘金上有很多Kotlin學習總結,但是基本上都是把官方文件一字不落地複製貼上了過來。我不希望自己也是這樣子的,因此在Kotlin學習之

數據庫知識體系梳理

DDL DCL DML DQL 關系型數據庫的特點(1)以二維表的形式來存放數據信息(2)傳統企業使用Oracle(有資本),互聯網企業使用MySQL(開源免費,社區人群多)(3)SQL語句是管理數據的關鍵(4)安全性方面(ACID)2.MySQL版本選擇(1)我接觸的最早的版本是2009-2

hadoop學習筆記hdfs體系結構讀寫流程

sim 百萬 服務器 發表 繼續 什麽 lose 基於 一次 原文:https://www.cnblogs.com/codeOfLife/p/5375120.html 目錄 HDFS 是做什麽的 HDFS 從何而來 為什麽選擇 HDFS 存儲數據 HDFS

知識體系梳理

tile 隔離級別 知識 級別 pri 場景 ola kafka cap理論 ** 分布式 1、分布式架構及CAP理論 2、zookeeper 3、RPC框架(如Dubbo、Spring Cloud) 4、消息隊列(Kafka),各種消息隊列的優劣 一、Java虛擬機

Ubuntu16.04CUDA學習筆記GPU背景知識

host:CPU,記憶體 device:GPU,視訊記憶體 我是純粹小白,裡面的一些圖是根據我自己的理解畫的,可能並不一定對 一,GPU和CPU執行程式的區別 (圖片來源:CUDA_C_Programming-Guide) 可以看到GPU有跟多的cores,你可以先把cores理

Kotlin學習筆記為什麼要學習kotlinkotlin的整合

Google在2017年的I/O大會上已經宣佈kotlin正式成為Android的一級開發語言。 為什麼要學習Kotlin Google釋出申明,目前已經有35%的Android專業開發人員使用kotlin(爆發式增長) Google與Oracle源於

、python學習筆記記憶體管理

變數和記憶體管理的 細節, 包括: 變數無須事先宣告 變數無須指定型別 程式設計師不用關心記憶體管理 變數名會被“回收” del 語句能夠直接釋放資源 1、變數定義 變數只有被建立和賦值後才能被使用 2、動態型別 還要注意一點,Python 中不但變數名無需事

【 專欄 】- Android知識體系

Android知識體系 收納了Android知識體系中個大類知識點,比如IPC, View實踐和事件機制,四大元件原始碼分析,訊息機制等。 加入了很多原始碼解析,適合對Android有些基礎。 主要對Android體系進行梳理

Android知識體系總結之Android部分之冷啟動&熱啟動篇

Android知識體系總結之Android部分之冷啟動&熱啟動篇 1.冷啟動&熱啟動 1.1 什麼是冷啟動?   當啟動應用時,後臺沒有該應用的程序,這時系統會重新建立一個新的程序分配給該應用,這個啟動方式就是冷啟動。它的特點就是冷啟動因為系統

Android知識體系總結(方面覆蓋Android知識結構,面試&進階)

Android知識體系總結(全方面覆蓋Android知識結構,面試&進階 Version-1.0.1 時間:2018.09) 基本內容 : Android基礎知識:基本涵蓋Android所有知識體系,四大元件,Fragment,WebView,事件分

Android知識體系學習及總結

前言 接觸安卓領域已經有超過兩年了,但是知識體系一直較為零散,所以打算從頭開始構建完整的安卓知識體系,全面系統的學習一遍安卓知識。 俗話說了,好記性不如爛筆頭,所以決定邊學習邊總結記錄,以便今後的溫習檢視;分享出來呢,也是希望與大家共同進步,歡迎志同道合的小

Android知識體系

這個知識體系圖適用於Android培訓講師培訓有Java基礎的學生 〇、Java基礎 1、假設培訓生有Android所需的Java基礎2、假設培訓生了解XML標記語言一、Gradle環境和Android Studio編譯器1、初識Gradle環境2、Android Su

Android知識體系總結之實戰經驗部分之Android多渠道打包與apk簽名篇

1.基礎知識 1.1 什麼是打包?   打包就是根據簽名和其它標識生成安裝包。 1.2 簽名是什麼?   在Android中,簽名就是apk中儲存的一串特別的字串。它是用來標識不同的應用開發者,為什麼取名為簽名,就好像一個作家一樣,它完成的小說都要加上署名。因

Kotlin學習筆記NotImplementedError: An operation is not implemented

// 自定義的一個介面 interface OnTestCallback{ fun onTest() } // 用快捷方法生成介面內的方法 setOnTestCallback(object :OnTestCallback{ ov

kotlin學習筆記object關鍵字介紹與java中的靜態變數與靜態方法的實現以及@JvmField@JvmStatic的使用

在java中,靜態變數和靜態方法是我們經常需要用到的東西,但是我們在kotlin中,並不能找到static關鍵字。其實目前在kotlin中,也的確是static概念的,那麼我們該如何在kotlin中實現靜態變數和靜態方法呢?這時就要用到kotlin中的obje

Kotlin學習筆記介面,可見性修飾符

介面 Kotlin中,使用關鍵字interface定義一個介面。與Java8類似,介面中即可以包含抽象方法的宣告,也可以包含實現。與抽象類不同的時,介面不儲存屬性的狀態,屬性要麼宣告為抽象,要麼提供訪問器實現。並且在介面中宣告的屬性沒有幕後欄位,所以在訪問

Kotlin學習筆記之一Kotlin基礎

1.函式: /** * 關鍵詞fun 申明是函式 * 引數形式:引數名:型別 * Kotlin中陣列是一個類 * 這是一個不帶返回值的函式 */ fun main(args: Array<String>){ println("