Android KTX.–与Kotlin的Android开发

介绍

Android KTX是一个开源库或一组功能,旨在通过Kotlin进行Android开发更令人愉快。您可以找到它的网站 这里。缩写ktx代表kotlin扩展,因此该库基本上是一组扩展函数,扩展属性和其他顶级函数。在本文中,我们看一下这个图书馆内部的内容以及我们如何利用它。此库的目标不是为现有的Android API添加新功能,而是通过利用Kotlin语言的功能来使这些API更易于使用。

Android KTX的结构

在开始时要注意的非常重要的是Android KTX提供了大部分时间将在开发人员添加到许多个人项目中的功能。可以说,也可以通过添加依赖关系来包括许多事情,这些依赖性不会被使用。非常感谢 proguard.,所有未使用的代码都会被剥离,因此在图书馆足迹不应该有担心。现在,让我们来看看Kotlin语言的一些非常重要和重要的概念,用于构建Android KTX。

扩展功能

An extension function is one of the Kotlin features that allows us to add a functionality to an existing class without modifying it directly. By adding extension functions to a class, they are represented as simple static methods on bytecode level. Then, we can call those functions on the objects of that class type, just as they were part of the class's API initially. Here is an example to give a little better insight into the way it's done. Say, we want to add an extension function to the String class to print itself. Here is how we can do it:

fun String.printSelf() {
    println(this)
}

Inside the extension function, we can use 这个 to refer to the current object on which the function is being executed. Then, this function becomes available to be called on any object of String type. So we can do:

fun usage() {
    "Kotlin Rocks".printSelf()
}

扩展属性

与扩展功能类似,Kotlin支持扩展属性。此外,我们定义它们的方式是相同的:

val String.isLongEnough: Boolean
    get() = this.length > 5

Then, we can use this extension property on any object of String type:

"Kotlin".isLongEnough

The behavior of the extension property can only be defined by explicitly providing getter (plus setter for vars). Initializing those properties the ordinary way doesn't work. The reason behind this is that an extension property does not insert members into the type, so there is no efficient way for it to have a 支持领域.

顶级功能

In Kotlin, a function is a first-class citizen. We are allowed to define functions in Kotlin files (.kt) which could afterward be accessed and used from other Kotlin files. This is a very powerful concept. If we define a file inside a package com.example and define functions in it, they can be used simply by importing them into the usage side. Here is an example:

package com.example

fun sum(x: Int, y: Int): Int = x + y

现在,可以通过简单地将其访问和使用此功能来访问和使用任何其他kotlin文件:

import com.example.sum

fun test() {
    println(sum(1, 2))
}

An important note here is the access modifier. In the example above, the function sum does not have defined an access modifier, and in Kotlin it's public 经过 default. Being public, it makes the sum function accessible from any other Kotlin file. Kotlin also has an internal access modifier keyword, which would make this function accessible only in the module where this file exists (a 模块 could contain many different packages). Ultimately, the function could also be private which will make it accessible only from inside the file where it is defined.

默认参数

最重要的是,您已经熟悉Java中的超载概念。重载是一个概念,允许我们定义具有相同签名的构造函数或方法,仅在其参数列表中不同(参数的两种类型和数量不同)。在Kotlin中,通过将默认值指定为某些或全部参数,通过将默认值定义单个函数来实现这一概念进一步进一步逐步实现相同的结果。最终,它归结为java中使用的方法。让我们来看看以下例子:

fun greet(firstName: String, lastName: String = "") {
    println("Hello $firstName $lastName")
}

In this example, the function takes two arguments, but the lastName is optional because by default its value is going to be an empty String. So, when calling this function we are only required to supply a firstName, and we can call it this way:

greet("John")

Kotlin还支持名为Arguments,因此我们可以通过他们的名称调用提供参数的函数:

greet("John", lastName = "Doe")

当我们具有多个可选参数的函数时,这尤其有用,并且我们希望仅使用仅提供特定的参数或以不同的顺序调用它。

您可以阅读更多关于Kotlin的令人敬畏的功能的更多信息 这个 article.

深入进入Android KTX

现在,正如我们知道Android KTX库的基础上,让我们挖掘并观察一些最常见的扩展功能。

将URL转换为URI

To begin with, there is a very simple extension function on the Uri class. Many times in Android, we need to convert a String URL into a Uri object, for instance when creating an Intent with data etc. The way we are usually doing this is by calling Uri.parse("string_url"). Android KTX defines an extension function that does the job. Here is how it looks like:

inline fun String.toUri(): Uri = Uri.parse(this)

so we can use it by calling toUri() on any string, like this:

"any_sting_url".toUri()

编辑共享偏好

Next, let's take a look at an extension function defined on the SharedPreferences interface. The usual way of putting values into the SharedPreferences in Android is to call edit() in order to obtain the SharedPreferences.Editor instance. Then, we can insert the values by calling editor.putType("key", typeValue). After that, it is very important to call apply() or commit() on the editor, in order for the values to be stored in the SharedPreferences. Many times we forget doing so, and we waste some time debugging until we notice what is happening. A usual example of storing values in the SharedPreferences looks like this:

val editor = sharedPreferences.edit()
editor.putString("key", value)
editor.apply()

By using the Android KTX extension on the SharedPreferences the code shortens and simplifies quite a lot, and it becomes:

sharedPreferences.edit {
    putString("key", value)
}

相关的扩展函数如下所示:

inline fun SharedPreferences.edit(
    commit: Boolean = false,
    action: SharedPreferences.Editor.() -> Unit
) {
    val editor = edit()
    action(editor)
    if (commit) {
        editor.commit()
    } else {
        editor.apply()
    }
}

The first parameter to this function is a Boolean value that controls the call to the editor, whether it would use the commit() or the apply() call. Clearly, by default this value is set to false which means by default the function will call apply() on the editor. A more interesting parameter is the second one. It's a function literal with a receiver, and the receiver is of type SharedPreferences.Editor. It means that when calling this function, we can use lambda over the receiver, so we can directly call functions that are exposed by the receiver type without additional qualifiers. This is shown with the putString call.

在绘图之前在视图下进行操作

Most of the apps we are using every day are having some sort of lists where some images are being loaded. Often, those images are of a different size, and the image sizes are usually provided in the response. Since the images are normally loaded in the background, we want to allocate the space required for the image to be displayed, and once it's loaded we already have the space allocated, so we would avoid UI expanding when the image is being displayed, which prevents the UI flickering effect. This is usually done by using a ViewTreeObserver which provides an OnPreDrawListener. This listener has a callback that is being called before the view drawing. For our images example, usually we set the view sizes that are provided in the response inside this callback, and we apply some default background (for example gray). That is one of the many use cases of the ViewTreeObserver observer and its OnPreDrawListener. Here is a snippet that shows the way we normally approach it:

view.viewTreeObserver.addOnPreDrawListener(
    object : ViewTreeObserver.OnPreDrawListener {
        override fun onPreDraw(): Boolean {
            viewTreeObserver.removeOnPreDrawListener(this)
            performSomethingOverTheView()
            return true
        }
    })

Android KTX.has defined an extension function on the View type named doOnPreDraw() that simplifies the above snippet, so it would become:

view.doOnPreDraw {
     performSomethingOverTheView()
}

There are also some other nice extensions defined on the View type which are working with the view visibility, updating view padding or layout params etc.

使用捆绑

捆绑在Android中是一个非常常见的东西,但与捆绑合作通常是一个相当一块。我们通常撰写捆绑包的方式如下所示:

val bundle = Bundle()
bundle.putString("key", "value")
bundle.putString("keyBoolean", true)
bundle.putString("keyInt", 1)

Android KTX.defines a top-level function named bundleOf(), and by using it, composing bundle becomes a lot nicer:

val bundle = bundleOf("key" to "value", "keyBoolean" to true, "keyInt" to 1)

There is also a persistableBundleOf() function for creating a PersistableBundle but it's available for API version 21 and up. Similarly, there is a contentValuesOf() function that could be used in the same way as the functions for creating bundle above, and it returns a ContentValues object.

迭代在视图组

使用 viewgroup. 在Android是一个很常见的事情。这 viewgroup. 是一种可以包含其他名为儿童的观点的容器。多次我们需要循环通过其子女,但传统的方式也可能很乱。 Android KTX定义了一个暴露子女的扩展属性,这里是它看起来的样子:

val ViewGroup.children: Sequence<View>
    get() = object : Sequence<View> {
        override fun iterator() = this@children.iterator()
    }

正如我们所看到的,孩子们属性正在返回一系列儿童视图,它允许我们在任何内容上写非常简洁的循环 viewgroup. type:

viewGroup.children.forEach {
    doSomething(it)
}

显示吐司

One of the most common ways of displaying some sort of short info to the user is a Toast. When displaying a toast by using the standard API, we have to pass the Context, the actual message that we want to be displayed, whether it is a String or a resource reference to load value from the strings.xml, and the toast duration. Since we cannot display a toast without having a Context, and since most of the time the toast duration is its Toast.LENGTH_SHORT constant, it would be great to have an option to display a toast by simply calling a function and passing the actual message argument. A common way to achieve this is by defining some sort of base class that defines such method, and then it would be called from the subclasses. However, Android KTX defines an extension functions to the Context type for displaying toasts. It takes 2 arguments, the message and the duration, while the duration is being set to Toast.LENGTH_SHORT 经过 default. So we can call to display toast wherever we have a Context 经过 simply passing the message argument, whether it is a String type or a reference to the string resources:

toast("Hello")
toast(R.string.hello)

包起来

Android KTX.is a very nice part of the Android Jetpack. 项目,并且正如我们所看到的,它包含了更好的改进我们习惯的努力发展方法。如前所述,它不提供任何新功能,而是简化了Android SDK已经提供的API。 这里 是一个很好的谈话 谷歌I / O 2018 经过 杰克沃顿, where he elaborates more on the Android KTX. This article only scratches the surface, and there are many more fun things to be revealed inside the Android KTX, related to animation, database, location, graphics, text and so on. Also, the team is welcoming new contributions, which is great, so if you have an idea that is not there yet, feel free to submit it.

3 thoughts on “Android KTX.–与Kotlin的Android开发

发表评论

您的电子邮件地址不会被公开。 必需的地方已做标记 *