Android的Kotlin秘方(I):OnGlobalLayoutListener
春节后,又重新“开张”。各位高手请继续支持。谢谢!
原文标题:Kotlin recipes for Android (I): OnGlobalLayoutListener
原文链接:http://antonioleiva.com/kotlin-ongloballayoutlistener/
原文作者:Antonio Leiva(http://antonioleiva.com/about/)
原文发布:2016-03-16
Android的Kotlin秘方(I):OnGlobalLayoutListener

今天一位同伴问我怎样恰当使用OnGlobalLayoutListener,而不需要太多的模板。这是一个棘手的问题,我们需要进一步深入研究。
OnGlobalLayoutListener是干什么的?
这个侦听器对于任何试图的ViewTreeObserver都适用,并且在已知视图宽度和高度进行各种计算、动画等等时,为扩展和测量视图常常回调它。
幸亏Kotlin提供很好的与Java互操作性,我们能够以一种非常清晰的方法 —— 使用它的模拟属性和Lambda表达式 —— 实现单一方法接口:
recycler.viewTreeObserver.addOnGlobalLayoutListener {
// do whatever
}
这里有什么问题吗?为了预防泄漏,推荐的实践是在完成使用它后,立即删除这个侦听器。但是由于使用了Lambda表达式,Lambda没有对象那么精确,我们没有对象的引用。
原方式还是可以用,但是在Kotlin中直接用匿名对象,每次都会有一只小猫死去。如果仍然需要做下面这样的事,没法改用更好开发语言:
recycler.viewTreeObserver.addOnGlobalLayoutListener(
object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
recycler.viewTreeObserver.removeOnGlobalLayoutListener(this);
// do whatever
}
});
找一个更佳替换方法
好了,既已知不要那样做。那么有什么更好的方法吗?我们被迫使用一种看上去没有那么好看的方法,但是可能是一种好的选择,将扩展函数隐藏起来。
为视图接收另一个函数创建一个新函数,由它自己创建和删除侦听器。就像这样:
inline fun View.waitForLayout(crossinline f: () -> Unit) = with(viewTreeObserver) {
addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
removeOnGlobalLayoutListener(this)
f()
}
})
}
现在你就可以调用这个函数,确保其自己添加和删除侦听器。除非,你永远不会忘记删除:
recycler.waitForLayout {
// do whatever
}
如果喜欢,可以用扩展ViewTreeObserver的函数,而不是直接用View。这取决你。
但是我们仍可以改进它
这是在测试视图后布局侦听器通常要做的一些事,所以需要等待宽度和高度大于0。而且可能要在视图中调用它时做一些事,这为什么不能转换参数函数到扩展函数?
我还泛型该函数使它能够在任何继承View的对象中使用,也能够从编写的函数中访问所有它的指定函数和属性。
inline fun <T: View> T.afterMeasured(crossinline f: T.() -> Unit) {
viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
if (measuredWidth > 0 && measuredHeight > 0) {
viewTreeObserver.removeOnGlobalLayoutListener(this)
f()
}
}
})
}
这个afterMeasured函数非常类似前者,但是在Lambda表达式内直接用视图的属性和public方法。例如,我们能够得到recycler的宽度和基于它用列的动态数组设置布局。
recycler.afterMeasured {
val columnCount = width / columnWidth
layoutManager = GridLayoutManager(context, columnCount)
}
总结
在Android中运行时,这确实仍有些事情做的不是很好,即使是移植Kotlin,但是总是可以通过隐藏在其他结构背后的不确定因素,找到提升可读性和避免不确定因素的选择。至少,仅需要编写一次,而其它代码则非常漂亮!
Android的Kotlin秘方(I):OnGlobalLayoutListener的更多相关文章
- Android的Kotlin秘方(II):RecyclerView 和 DiffUtil
作者:Antonio Leiva 时间:Sep 12, 2016 原文链接:http://antonioleiva.com/recyclerview-diffutil-kotlin/ 如你所知,在[支 ...
- [Android]使用Kotlin开发Android(二)
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4829007.html [TOC] 使用Kotlin+OkHtt ...
- Google Android Studio Kotlin 开发环境配置
Google 近日开发者大会宣布Kotlin成为Android开发的第一级语言,即Android官方开发语言,可见Google对Kotlin的重视,本文就介绍一下Android Studio下的Kot ...
- Google Android Studio Kotlin
Google Android Studio Kotlin 开发环境配置 Google 近日开发者大会宣布Kotlin成为Android开发的第一级语言,即Android官方开发语言,可见Google对 ...
- [Android]使用Kotlin+Anko开发Android(一)
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4800656.html Kotlin是由JetBrains开发 ...
- 在Android中用Kotlin的Anko运行后台任务(KAD 09)
作者:Antonio Leiva 时间:Jan 19, 2017 原文链接:https://antonioleiva.com/anko-background-kotlin-android/ Anko是 ...
- 让你的代码量减少3倍!使用kotlin开发Android(四) kotlin bean背后的秘密
上一篇我们介绍了缩短五倍的java bean,不知道你在看的时候有没有一种疑问捏? 本文同步自博主的私人博客wing的地方酒馆 再来回顾一下,两种代码的对比 public class User { p ...
- Getting started with Android and Kotlin (译文)
原文链接 http://kotlinlang.org/docs/tutorials/kotlin-android.html 写在前面 Kotlin 是一个基于 JVM 的新的编程语言,由 JetBra ...
- 在Android上Kotlin的单元测试(KAD22)
作者:Antonio Leiva 时间:Apr 25, 2017 原文链接:https://antonioleiva.com/unit-tests-android-kotlin/ 当然,Kotlin也 ...
随机推荐
- 使用 Roslyn 编译器服务
.NET Core和 .NET 4.6中 的C# 6/7 中的编译器Roslyn 一个重要的特性就是"Compiler as a Service",简单的讲,就是就是将编译器开放为 ...
- 我是如何在SQLServer中处理每天四亿三千万记录的
首先声明,我只是个程序员,不是专业的DBA,以下这篇文章是从一个问题的解决过程去写的,而不是一开始就给大家一个正确的结果,如果文中有不对的地方,请各位数据库大牛给予指正,以便我能够更好的处理此次业务. ...
- 前端学HTTP之实体和编码
前面的话 每天都有各种媒体对象经由HTTP传送,如图像.文本.影片以及软件程序等.HTTP要确保它的报文被正确传送,识别.提取以及适当处理.为了实现这些目标,HTTP使用了完善的标签来描述承载内容的实 ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(68)-微信公众平台开发- 资源环境准备
系列目录 前言: 本次将学习扩展企业微信公众号功能,微信公众号也是企业流量及品牌推广的主要途径,所谓工欲善其事必先利其器,调试微信必须把程序发布外网环境,导致调试速度太慢,太麻烦! 我们需要准备妥当才 ...
- MAC Osx PHP安装指导
php.ini的位置 Mac OS X中没有默认的php.ini文件,但是有对应的模版文件php.ini.default,位于/private/etc/php.ini.default 或者说 /etc ...
- C#使用Aspose.Cells导出Excel简单实现
首先,需要添加引用Aspose.Cells.dll,官网下载地址:http://downloads.aspose.com/cells/net 将DataTable导出Xlsx格式的文件下载(网页输出) ...
- Android中Fragment和ViewPager那点事儿(仿微信APP)
在之前的博文<Android中使用ViewPager实现屏幕页面切换和引导页效果实现>和<Android中Fragment的两种创建方式>以及<Android中Fragm ...
- 信息安全-1:python之playfair密码算法详解[原创]
转发注明出处: http://www.cnblogs.com/0zcl/p/6105825.html 一.基本概念 古典密码是基于字符替换的密码.加密技术有:Caesar(恺撒)密码.Vigenere ...
- 不要着急改代码,先想想--centos 6.8下编译安装tmux
诸位读者新年好,2017开年第一篇博客,请允许我先问候一下看到这篇博客的诸位.写博客是我2017年定下的目标之一,希望我会坚持下去. 最近打算尝试一下tmux这个神器,于是有了这一篇关于思维方式的Bl ...
- 在树莓派Raspbian下安装支持Hard Float的.NET环境
[题外话] 最近入了个树莓派玩,系统装的官方推荐的Hard Float的Raspbian,由于衍生自Debian,所以Mono什么的非常好装.但是官方源中的Mono在Hard Float的Raspbi ...