Skip to content

Latest commit

 

History

History
108 lines (77 loc) · 5.31 KB

9.Kotlin_androidktx.md

File metadata and controls

108 lines (77 loc) · 5.31 KB

9.Kotlin_androidktx

相信每一位安卓开发人员对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中的声明具有同样类型。

这里,你肯定会想,虽然省略了R.id.几个字符,但是引入是否会造成性能问题? 值得引入、使用 kotlin-android-extensions吗?如果我们对其反编译,就可以看到对应Java代码的实现,在第一次使用空间的时候,会在缓存集合中进行查找,有就直接使用,没有就通过findViewById进行查找,并添加到缓存的集合中。其还提供了$clearFindViewByIdCache()方法用于清除缓存,在我们想要彻底替换界面控件时可以使用。

在Fragment的onDestroyView()方法中默认调用了$clearFindViewByIdCache()清除缓存,而Activity没有。

所以我们并没有完全离开findViewById,只是Kotlin的扩展插件利用缓存的方式让我们开发更方便、更快捷。

网络请求

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