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 通过 tecode 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. 这里 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. 这里 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, 这个 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() = 这个.length > 5

Then, we can use 这个 extension property on any object of String 类型:

"Kotlin".isLongEnough

The behavior of the extension property can only be defined 通过 explicitly providing getter (plus setter for vars). Initializing those properties the ordinary way doesn't work. The reason behind 这个 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 通过 importing them into the usage side. 这里 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 这里 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 这个 function accessible only in the 模组 where 这个 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 这个 example, the function takes two arguments, but the lastName is optional because 通过 default its value is going to be an empty String. So, when calling 这个 function we are only required to supply a firstName, and we can call it 这个 way:

greet("John")

Kotlin还支持命名参数,因此我们可以调用一个函数,以其名称提供参数:

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

当我们有一个带有多个可选参数的函数并且希望仅提供特定的参数或以不同的顺序调用它时,此功能特别有用。

您可以在中阅读有关Kotlin出色功能的更多信息 这个 文章。

深入研究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 这个 is 通过 calling Uri.parse("string_url"). Android KTXdefines an extension function that does the job. 这里 is how it looks like:

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

so we can use it 通过 calling toUri() on any string, like 这个:

"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 通过 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 这个:

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

By using the Android KTXextension 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 这个 function is a Boolean value that controls the call to the editor, whether it would use the commit() or the apply() call. Clearly, 通过 default 这个 value is set to false which means 通过 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 这个 function, we can use lambda over the receiver, so we can directly call functions that are exposed 通过 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 通过 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 这个 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. 这里 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 KTXhas 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 KTXdefines a top-level function named bundleOf(), and 通过 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.

遍历视图组

与...合作 视图组 在Android中是很平常的事情。的 视图组 是一种可以包含称为子视图的其他视图的容器。很多时候,我们需要遍历其子级,但是传统的方法可能会很混乱。 Android KTX定义了一个扩展属性,用于公开其子级,其外观如下所示:

val 视图组.children: Sequence<View>
    get() = object : Sequence<View> {
        override fun iterator() = 这个@children.iterator()
    }

如我们所见,children属性返回一个子视图序列,它使我们能够在任何 视图组 类型:

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 通过 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 通过 simply calling a function and passing the actual message argument. A common way to achieve 这个 is 通过 defining some sort of base class that defines such method, and then it would be called from the subclasses. However, Android KTXdefines 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 KTXis a very nice part of the Android JetPack 项目,并且正如我们所见,它包含了许多改善我们惯用的Android开发的好方法。如前所述,它没有提供任何新功能,而是简化了Android SDK已提供的API。 这里 是一个很好的谈话 Google I / O 2018 通过 杰克·沃顿, where he elaborates more on the Android KTX. This 文章 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个想法“Android KTX–用Kotlin开发Android

发表评论

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