Kotlin学习教程(九)

简介: Kotlin学习教程(九)

Kotlin学习教程(九)

参考往期教程:
Kotlin学习教程(一)
Kotlin学习教程(二)
Kotlin学习教程(三)
Kotlin学习教程(四)
Kotlin学习教程(五)
Kotlin学习教程(六)
Kotlin学习教程(七)
Kotlin学习教程(八)
Kotlin学习教程(九)
Kotlin学习教程(十)

Kotlin团队为Android开发提供了一套超越标准语言功能的工具:

  • Kotlin Android Extensions是一个编译器扩展,可以让您摆脱代码中的findViewById()调用,并将其替换为合成编译器生成的属性。
  • Anko是一个提供围绕Android APIDSL的一组Kotlin友好的包装器,可以用Kotlin代码替换layout .xml文件。

Anko

AnkoKotlin官方出品用于Android开发的库。

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 consists of several parts:

Anko Commons: a lightweight library full of helpers for intents, dialogs, logging and so on;
Intents;
Dialogs and toasts;
Logging;
Resources and dimensions;
Anko Layouts: a fast and type-safe way to write dynamic Android layouts;
Anko SQLite: a query DSL and parser collection for Android SQLite;
Anko Coroutines: utilities based on the kotlinx.coroutines library.

Anko使用DSL提供了很多便捷的功能,可以直接用代码去写布局,不过我还是接受不了,感觉用xml写布局把布局和逻辑区分开挺好,这里就不介绍了,想用的可以去看看。

这里就用几个简单的commons中的例子,平时想要启动另一个activity我们经常这样写:

val intent = Intent(this, SomeOtherActivity::class.java)
intent.putExtra("id", 5)
intent.setFlag(Intent.FLAG_ACTIVITY_SINGLE_TOP)
startActivity(intent)

这里要四行代码,太多了,anko提供了更简单的方式:

startActivity(intentFor<SomeOtherActivity>("id" to 5).singleTop())

如果不设置flag的话还可以这样写:

startActivity<SomeOtherActivity>("id" to 5)

而且anko还提供了一些常用的intent的封装功能:

  • 打电话makeCall(number) without tel
  • 发短信sendSMS(number, [text]) without sms
  • 浏览网页browse(url)
  • 分享share(text, [subject])
  • 发邮件email(email, [subject], [text])

进行toastsnakebar提示:

toast("Hi there!")
toast(R.string.message)
longToast("Wow, such duration")

snackbar(view, "Hi there!")
snackbar(view, R.string.message)
longSnackbar(view, "Wow, such duration")
snackbar(view, "Action, reaction", "Click me!") { doStuff() }

对话框:

alert("Hi, I'm Roy", "Have you tried turning it off and on again?") {
    yesButton { toast("Oh…") }
    noButton {}
}.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")

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

或者:

class SomeActivity : Activity() {
    private val log = AnkoLogger<SomeActivity>(this)
    private val logWithASpecificTag = AnkoLogger("my_tag")

    private fun someMethod() {
        log.warning("Big brother is watching you!")
    }
}

dimens:

可以直接使用px2dippx2sp来进行尺寸转换。

异步操作:

doAsync {
    // Long background task
    uiThread {
        result.text = "Done"
    }
}

使用anko:

// 创建一个verticallayout并且添加edittext和button,并给button设置点击事件
verticalLayout {
    val name = editText()
    button("Say Hello") {
        onClick { toast("Hello, ${name.text}!") }
    }
}

Kotlin Android Extensions

相信每一位安卓开发人员对findViewById()这个方法再熟悉不过了,毫无疑问,潜在的bug和脏乱的代码令后续开发无从下手的。 尽管存在一系列的
开源库能够为这个问题带来解决方案,然而对于运行时依赖的库,需要为每一个View注解变量字段。

现在Kotlin安卓扩展插件能够提供与这些开源库功能相同的体验,不需要添加任何额外代码,也不影响任何运行时体验。
另一个Kotlin团队研发的可以让开发更简单的插件是Kotlin Android Extensions。当前仅仅包括了view的绑定。这个插件自动创建了很多的属性
来让我们直接访问XML中的view。这种方式不需要你在开始使用之前明确地从布局中去找到这些views

这些属性的名字就是来自对应viewid,所以我们取id的时候要十分小心,因为它们将会是我们类中非常重要的一部分。这些属性的类型也是来自
XML中的,所以我们不需要去进行额外的类型转换。

Kotlin Android Extensions的一个优点是它不需要在我们的代码中依赖其它额外的库。它仅仅由插件组层,需要时用于生成工作所需的代码,只需要依赖
Kotlin的标准库。

开发者仅需要在模块的build.gradle文件中启用Gradle安卓扩展插件即可:

apply plugin: 'kotlin-android-extensions'

我们在使用Android Sutdio 3.0创建Kotlin项目时默认已经添加了该依赖。

// 使用来自主代码集的 R.layout.activity_main
import kotlinx.android.synthetic.main.activity_main.*

class MyActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        textView.setText("Hello, world!")
        // 而不是 findViewById(R.id.textView) as TextView
    }
}

textView是对Activity的一项扩展属性,与在activity_main.xml中的声明具有同样类型。

网络请求

Kotlin提供了一些扩展函数来执行网络请求,同时也可以使用第三方库来执行.

public class Request(val url: String) {
    public fun run() {
        val forecastJsonStr = URL(url).readText()
        Log.d(javaClass.simpleName, forecastJsonStr)
    }
}

如你所知,HTTP请求不被允许在主线程中执行,否则它会抛出异常。这是因为阻塞住UI线程是一个非常差的体验。Android中通用的做法是使用
AsyncTask,但是这些类是非常丑陋的,并且使用它们无任何副作用地实现功能也是非常困难的。Anko提供了非常简单的DSL来处理异步任务,
它满足大部分的需求。它提供了一个基本的async函数用于在其它线程执行代码,也可以选择通过调用uiThread的方式回到主线程。
在子线程中执行请求如下这么简单:

async() {
    Request(url).run()
    uiThread { longToast("Request performed") }
}

UIThread有一个很不错的一点就是可以依赖于调用者。如果它是被一个Activity调用的,那么如果activity.isFinishing()返回true
uiThread不会执行,这样就不会在Activity销毁的时候遇到崩溃的情况了。

解析gson

Kotlin允许我们去定义一些行为与静态对象一样的对象。尽管这些对象可以用众所周知的模式来实现,比如容易实现的单例模式。
我们需要一个类里面有一些静态的属性、常量或者函数,我们可以使用companion objecvt。这个对象被这个类的所有对象所共享,就像Java中的静态
属性或者方法。

public class ForecastRequest(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="
    }

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

创建Application

class App : Application() {
    companion object {
        private var instance: Application? = null
        fun instance() = instance!!
    }
    override fun onCreate() {
        super.onCreate()
        instance = this
    }
}
  • with()
inline fun <T> with(t: T, body: T.() -> Unit) { t.body() }

参考


相关文章
|
9天前
|
算法 Kotlin
Kotlin教程笔记(24) -尾递归优化
Kotlin教程笔记(24) -尾递归优化
24 7
Kotlin教程笔记(24) -尾递归优化
|
10天前
|
Java Kotlin
​ Kotlin教程笔记(15) - 方法重载与默认参数
​ Kotlin教程笔记(15) - 方法重载与默认参数
18 4
​ Kotlin教程笔记(15) - 方法重载与默认参数
|
9天前
|
Kotlin
Kotlin教程笔记(20) - 枚举与密封类
Kotlin教程笔记(20) - 枚举与密封类
28 8
|
9天前
|
安全 Java 编译器
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
|
9天前
|
Java 开发工具 Android开发
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
|
9天前
|
安全 Kotlin
Kotlin教程笔记(23) -作用域函数
Kotlin教程笔记(23) -作用域函数
24 6
|
9天前
|
Kotlin
Kotlin教程笔记(21) -高阶函数与函数引用
Kotlin教程笔记(21) -高阶函数与函数引用
23 6
|
9天前
|
缓存 Kotlin Python
Kotlin教程笔记(25) -函数式编程
Kotlin教程笔记(25) -函数式编程
|
8天前
|
设计模式 Java Kotlin
Kotlin教程笔记(56) - 改良设计模式 - 装饰者模式
Kotlin教程笔记(56) - 改良设计模式 - 装饰者模式
19 2
|
8天前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
14 2