相信每一位安卓开发人员对findViewById()
这个方法再熟悉不过了,毫无疑问,潜在的bug
和脏乱的代码令后续开发无从下手的。 尽管存在一系列的
开源库能够为这个问题带来解决方案,然而对于运行时依赖的库,需要为每一个View
注解变量字段。
现在Kotlin
安卓扩展插件能够提供与这些开源库功能相同的体验,不需要添加任何额外代码,也不影响任何运行时体验。
另一个Kotlin
团队研发的可以让开发更简单的插件是Kotlin Android Extensions
。当前仅仅包括了view
的绑定。这个插件自动创建了很多的属性
来让我们直接访问XML
中的view
。这种方式不需要你在开始使用之前明确地从布局中去找到这些views
。
这些属性的名字就是来自对应view
的id
,所以我们取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
销毁的时候遇到崩溃的情况了。
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)
}
}
- 邮箱 :[email protected]
- Good Luck!