时间:Aug 16, 2017

原文链接:https://antonioleiva.com/kotlin-android-extensions/

在 Kotlin1.1.4版本 发布后,原作者依据 Kotlin 新版本的一系列新特性,以及有读者关于如何在 Fragment 和 custom view 中使用Kotlin 等等向他提问,原作者决定针对这些内容进行更新、重写几个月的文章。

在这篇重写的文章中,他涵盖了所有KAE(1.1.4版本前后)可以完成的事情。现在你会喜欢在任何类(不只是activity, fragment 或view)使用它们,包括一个新的注释来实现Parcelable。

你可能会厌倦日复一日地使用findViewById来恢复Androidview。或许你已放弃了,并开始使用著名的Butterknife库。那么你会喜欢上Kotlin Android Extensions。

Kotlin Android Extensions:这是什么?

Kotlin Android Extensions是Kotlin的一个插件,它包含在普通的那个插件中,这就允许以惊人的无缝方式从Activitie,Fragment和View中恢复View。

该插件将生成一些额外的代码,允许你访问布局XML的View,就像它们是在布局中定义的属性一样,你可以使用id的名称。

它还构建本地视图缓存。所以首次使用一个属性时,它会做一个普通的findViewById。而接下来,View则是从缓存中恢复,因此访问速度更快。

怎样使用它们

让我们看看它的使用是多么容易。我会以一个Activity做第一个例子:

将Kotlin Android Extensions集成到我们的代码中

虽然这个插件被集成到普通的插件(你不需要安装新的插件)中,但是,你要使用它,还必须在Android模块中添加额外的应用:

1 apply plugin: 'com.android.application'

2 apply plugin: 'kotlin-android'

3 apply plugin: 'kotlin-android-extensions'

只需要做这些,可以开始使用它了。

从XML中恢复View

从这一刻起,恢复View就像将你在XML中定义的View ID直接用于你的Activity一样简单。

假设你有一个这样的XML:

1 <?xml version="1.0" encoding="utf-8"?>

2

4 android:layout_width="match_parent"

5 android:layout_height="match_parent">

6

7

9 android:layout_width="wrap_content"

10 android:layout_height="wrap_content"

11 android:layout_gravity="center"

12 android:text="Hello World!"/>

13

14

如你所见,TextView有welcomeMessage ID。

在你的MainActivity中,仅仅需要这样编写:

1 override fun onCreate(savedInstanceState: Bundle?) {

2 super.onCreate(savedInstanceState)

3 setContentView(R.layout.activity_main)

4

5 welcomeMessage.text = "Hello Kotlin!"

6 }

为了能够使用它,你需要如下的import,而IDE能够自动加入它。不是很容易吗?

1 import kotlinx.android.synthetic.main.activity_main.*

如上所述,生成的代码将包括View缓存,因此再次询问视图,就不需要另一个findViewById。

让我们看看其背后都是什么。

Kotlin Android Extensions背后的魔力

在你开始使用Kotlin时,理解所使用特性时生成的字节码是非常有趣。这也有助于你了解在你的决定背后

在Tools-->Kotlin下,有一个强大的功能,称为显示Kotlin字节码(Show Kotlin Bytecode)。如果你点击它,你将看到当你打开的类文件编译后生成的字节码。

对大多数人来说,字节码并不是很有用,但是还有另一个选择:Decompile(反编译)。

这将显示由Kotlin生成的字节码的Java表示。所以你可以或多或少地了解你写的Kotlin代码对应Java的代码。

在我生成的Activity中使用它,并查看由Kotlin Android Extensions生成的代码。

有趣的是这一个:

1 private HashMap _$_findViewCache;

2 ...

3 public View _$_findCachedViewById(int var1) {

4 if(this._$_findViewCache == null) {

5 this._$_findViewCache = new HashMap();

6 }

7

8 View var2 = (View)this._$_findViewCache.get(Integer.valueOf(var1));

9 if(var2 == null) {

10 var2 = this.findViewById(var1);

11 this._$_findViewCache.put(Integer.valueOf(var1), var2);

12 }

13

14 return var2;

15 }

16

17 public void _$_clearFindViewByIdCache() {

18 if(this._$_findViewCache != null) {

19 this._$_findViewCache.clear();

20 }

21

22 }

这就是我们正在谈论的视图缓存(View Cache)。

在要求查看时,首先会尝试在缓存中找。如果它不存在,它会查找它,并将其添加到缓存。非常简单。

此外,它还添加了一个清除缓存的功能:clearFindViewByIdCache。如果你必须重建视图,因为旧视图将不再有效,就可以使用它。

那么这一行:

1 welcomeMessage.text = "Hello Kotlin!"

则转换为:

1 ((TextView)this._$_findCachedViewById(id.welcomeMessage)).setText((CharSequence)"Hello Kotlin!");

因此,属性不是真实的,插件不会为每个视图生成属性。在编译期间,只需要替换代码即可访问视图缓存,将其转换为正确的类型并调用该方法。

Fragment的 Kotlin Android Extensions

这个插件也能够用于Fragment。

Fragment的问题是View可以重新创建,而Fragment实例却保持有效。这会怎么样?这就意味着缓存中的视图将不再有效。

如果我们把View移动到Fragment中,我们来看看生成的代码。这是我创建这个简单的Fragment,它使用与上面写的相同的XML:

1 class Fragment : Fragment() {

2

3 override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {

4 return inflater.inflate(R.layout.fragment, container, false)

5 }

6

7 override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {

8 super.onViewCreated(view, savedInstanceState)

9 welcomeMessage.text = "Hello Kotlin!"

10 }

11 }

在onViewCreated中,我再次更改TextView的文本。生成怎样的字节码呢?

一切都与Activity中的一样,仅有一个微小的区别:

1 //$FF: synthetic method

2 public void onDestroyView() {

3 super.onDestroyView();

4 this._$_clearFindViewByIdCache();

5 }

当View被销毁时,此方法将调用clearFindViewByIdCache,所以我们是安全的!

自定义View的Kotlin Android extensions

在自定义视图下,Kotlin Android extensions非常类似。假设我们有这样的View:

1

2 android:orientation="vertical"

3 android:layout_width="match_parent"

4 android:layout_height="match_parent">

5

6

7 android:id="@+id/itemImage"

8 android:layout_width="match_parent"

9 android:layout_height="200dp"/>

10

11

12 android:id="@+id/itemTitle"

13 android:layout_width="match_parent"

14 android:layout_height="wrap_content"/>

15

16

我创建一个非常简单的自定义视图,并使用@JvmOverloads注释的新Intent生成构造函数:

1 class CustomView @JvmOverloads constructor(

2 context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0

3 ) : LinearLayout(context, attrs, defStyleAttr) {

4

5 init {

6 LayoutInflater.from(context).inflate(R.layout.view_custom, this, true)

7 itemTitle.text = "Hello Kotlin!"

8 }

9 }

在上面的示例中,我将文本更改为itemTitle。生成的代码应该尝试从缓存中查找View。再次复制所有相同的代码已无意义了,但是你可以在更改文本的行中看到这一点:

1 ((TextView)this._$_findCachedViewById(id.itemTitle)).setText((CharSequence)"Hello Kotlin!");

太棒了!在自定义View中,我们只是首次调用findViewById。

从另一个View中恢复View

Kotlin Android Extensions提供的最后一个选择是直接从另一个视图使用属性。

我用与上节非常相似的布局。假设一下这是在适配器(Adapter)中对实例进行inflate。

使用此插件,你还可以直接访问子视图(subview):

1 val itemView = ...

2 itemView.itemImage.setImageResource(R.mipmap.ic_launcher)

3 itemView.itemTitle.text = "My Text"

虽然这个插件会帮你填写import,但是在这方面还是有点不同:

1 import kotlinx.android.synthetic.main.view_item.view.*

这里有几件事情,你需要了解:

在编译时,你可以从任何其他视图(View)引用任何视图。 这意味着你可以引用一个视图,该视图不是其的直接子节点。 但是,当试图尝试恢复不存在的视图时,执行会失败。

在这种情况下,视图不像Activity和Fragment那样被缓存。

为什么会这样?与之前的情况相反,这里的插件没有地方可以为缓存生成所需的代码。

如果你再次查看代码,它是当从视图调用属性时由插件生成的,你会看到:

1 ((TextView)itemView.findViewById(id.itemTitle)).setText((CharSequence)"My Text");

如你所见,没有调用缓存。如果你的视图很复杂,而且你是在适配器中使用,请注意,它可能会影响性能。

或者你可以选择:Kotlin 1.1.4

版本1.1.4中的Kotlin Android Extensions

Kotlin新版本中,Android Extensions已经引入了一些新的有趣的功能:任何类中的缓存(有趣的包括ViewHolder)和一个新的@Parcelize注释。还有一种方法可以自定义生成的缓存。

稍后,我们会看到它们,但你需要知道这些功能并不是最终的版本,所以你需要将它们添加到build.gradle中来启动它们:

1 androidExtensions {

2 experimental = true

3 }

在ViewHolder(或任何自定义类)中使用它

现在,你可以通过简单的方式在任何类中构建缓存。唯一要求是你的类要实现LayoutContainer接口。该接口将提供一个视图,它是由插件查找的子视图。假设,我们有一个ViewHolder,它保持前面示例中讲述的布局视图。你只需要做:

1 class ViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView),

2 LayoutContainer {

3

4 fun bind(title: String) {

5 itemTitle.text = "Hello Kotlin!"

6 }

7 }

containerView是我们从LayoutContainer接口覆盖的。但这就是你需要的。

之后,你就可以直接访问视图,无需使用前置itemView来访问子视图。

另外,如果你检查生成代码,你会看到它从缓存中获取视图:

1 ((TextView)this._$_findCachedViewById(id.itemTitle)).setText((CharSequence)"Hello Kotlin!");

这里,我已经在ViewHolder上使用了它,但是你可以看到这是通用的,完全可以在任何类中使用。

Kotlin Android Extension实现Parcelable

用新的@Parcelize注释,你可以以非常简单的方式使任何类都能实现。

你只需要添加注释,插件就会完成所有复杂的工作:

1 @Parcelize

2 class Model(val title: String, val amount: Int) : Parcelable

然后,如你所知,你可以将对象添加到任何intent中:

1 val intent = Intent(this, DetailActivity::class.java)

2 intent.putExtra(DetailActivity.EXTRA, model)

3 startActivity(intent)

并且在任何位置(在这种情况下是在在目标Activity)上,从intent恢复对象:

1 val model: Model = intent.getParcelableExtra(EXTRA)

自定义构建缓存

在这组实验中包含的新功能是一个新注释@ContainerOptions。这允许你以自定义方式构建缓存,甚至阻止类创建它。

默认情况下,它将用Hashmap,如我们之前看到的那样。但是,这可以用Android框架的SparseArray来改变,这在某些情况下可能会更有效率。如果由于某种原因,你不需要一个类的缓存,你也可以使用该选项。

这是它的用法:

1 @ContainerOptions(CacheImplementation.SPARSE_ARRAY)

2 class MainActivity : AppCompatActivity() {

3 ...

4 }

目前,已有的选择是:

1 public enum class CacheImplementation {

2 SPARSE_ARRAY,

3 HASH_MAP,

4 NO_CACHE;

5

6 ...

7 }

结论

你已经看到Kotlin处理Android视图的如此简易。通过一个简单的插件,我们可以抛弃那些在inflation后视图恢复的所有可怕的代码。此插件将为我们创建所需的属性,而不会出现任何问题。

此外,Kotlin 1.1.4增加了一些有趣的特性,这些特性在以前的插件没有覆盖的情况下,是非常有用。

kotlin android 4,Kotlin Android Extensions: 与 findViewById 说再见 (KAD 04)相关推荐

  1. kotlin学习笔记——Kotlin Android Extensions

    Kotlin Android Extensions是另外一个团队开发的,它是一个插件所以不需要依赖别的库.当前仅仅包含view的绑定,会自动创建很多属性让我们直接访问xml中的view,我们就不需要明 ...

  2. kotlin中mainactivity无法直接调用xml中的控件_使用Kotlin高效地开发Android App(一)

    一.apply 函数 和 run 函数 1.1 apply函数 apply函数是指在函数块内可以通过 this 指代该对象,返回值为该对象自己.在链式调用中,可以考虑使用它来不破坏链式. /** * ...

  3. android 多结点进度条,Android使用Kotlin实现多节点进度条

    时间轴主要使用Recyclerview来实现.开发语言使用Kotlin,代码相对java少了许多也简洁许多 效果图: MainActivity.kt package com.example.lee.l ...

  4. kotlin button_使用Kotlin和XML的Android Button

    kotlin button In this tutorial, we'll learn how to create a Button in Android apps using Kotlin prog ...

  5. Android Studio kotlin编程实现图片滑动浏览 stepbystep

    1 基本介绍 参照 kotlin官网:使用 RecyclerView 显示可滚动列表的 案例实现 功能:采用RecyclerView 空间实现图片和文字的滚动浏览. 在下图显示的序列中,可以看到一个填 ...

  6. 《Kotin 极简教程》第13章 使用 Kotlin 和 Anko 的Android 开发

    第13章 使用 Kotlin 和 Anko 的Android 开发 最新上架!!!< Kotlin极简教程> 陈光剑 (机械工业出版社) 可直接打开京东,淘宝,当当===> 搜索: ...

  7. 《Kotlin 极简教程》第13章 使用 Kotlin 和 Anko 的Android 开发

    2019独角兽企业重金招聘Python工程师标准>>> 第13章 使用 Kotlin 和 Anko 的Android 开发 13.1 什么是 Anko? Anko (https:// ...

  8. Kotlin【简介】Android开发 配置 扩展

    重要资源 官方资源:官网 . 官网源码 .官网文档 . 在线 IDE .GitHub 中文资源:中文官网 .中文文档  离线文档:PDF 文件 . PDF 文件 GitBook 版 .ePUB 文件  ...

  9. kotlin 垂直滚动_在Android的Kotlin中检测点击或滚动

    kotlin 垂直滚动 Build a responsive UI that shows or hides the toolbar in response to user clicks whilst ...

最新文章

  1. Python,OpenCV轮廓属性、轮廓检测及绘制
  2. Android NDK 使用自己的共享库(Import Module)
  3. 争建AI算力中心热潮背后:谁在花冤枉钱?
  4. int p 和int p
  5. python接口测试上传文件_python https 接口测试 上传文件
  6. iOS 代理设计模式
  7. Windows下配置环境变量和需不需要重启?
  8. Egret 生成 自带EUI 的微信小游戏 踩坑!
  9. JQuery的ajax函数执行失败,alert函数弹框一闪而过
  10. 广度优先搜索 解决九宫格问题
  11. iOS 10 的一个重要更新-线程竞态检测工具 Thread Sanitizer
  12. 联想拯救者2020 Y7000安装Ubuntu16.04
  13. oracle查询平均每月数据,oracle 按每天,每周,每月,每季度,每年查询统计数据
  14. cmake 返回上层目录
  15. 创世神曲java官网_创世神曲官网下载
  16. CPU纯软件全虚拟化技术
  17. Docker容器技术与应用(项目1 Docker容器简介)
  18. 启动计算机按住del不放,惠普从光驱启动开始怎么做(包括hp笔记本)
  19. java http 服务器搭建_基于http.server搭建局域网服务器过程解析
  20. 如何关闭计算机服务检测,交互式服务检测老是弹出来?Win7系统交互式服务检测怎么关闭方法...

热门文章

  1. 基于CNN的图像识别(Tensorflow)
  2. plc西门子s300编程 西门子编程1000例
  3. matlab实现低通、高通、带通、带阻滤波
  4. Shell编程--变量的类型
  5. 2023最新姆町个人自动发卡系统源码+全开源的/功能丰富UI美观
  6. ​TOGAF认证自学宝典V3.0
  7. 我们如何全面转向 Kubernetes?
  8. openssl与数字证书的使用
  9. 2023 iApp 微信余额装逼源码
  10. STM32外部高速晶振不起振的故障分析