Kotlin开发实践之一-灵析社区

德州安卓

1.正确使用lazy委托

val vm: String by lazy { "" }

这种使用默认是加锁实现的,并发环境下使用没什么问题, 不过在非并发环境中比如Android主线程中未免会造成性能开销。

看下lazy的实现源码:

public actual fun <T> lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =
    when (mode) {
        LazyThreadSafetyMode.SYNCHRONIZED -> SynchronizedLazyImpl(initializer)
        LazyThreadSafetyMode.PUBLICATION -> SafePublicationLazyImpl(initializer)
        LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer)
    }

lazy懒加载支持三种模式:
LazyThreadSafetyMode.SYNCHRONIZED:添加同步锁,使lazy延迟初始化线程安全

LazyThreadSafetyMode.PUBLICATION:初始化的lambda表达式可以在同一时间被多次调用,但是只有第一个返回的值作为初始化的值

LazyThreadSafetyMode.NONE:非加锁实现,非线程安全

所以我们可以对lazy二次封装下,暴露出线程安全的lazy和不安全的lazy,根据具体的使用场景选择对应的方法调用
//线程安全
fun <T> safeLazy(initializer: () -> T): Lazy<T> =
    lazy(LazyThreadSafetyMode.SYNCHRONIZED, initializer)

//非线程安全
fun <T> unSafeLazy(initializer: () -> T): Lazy<T> =
    lazy(LazyThreadSafetyMode.NONE, initializer)

2.View.postDelay()优化使用

日常开发中,我们一般会使用View.postDelay()获取view的宽高信息,更可以在onResume中粗略估算界面绘制耗时:

mBinding.root.postDelayed({ println("size: ${mBinding.root.measuredHeight}") }, 1000)

但是这个原生的postDelayed写起来特别别扭,因为它的Runnable是放在第一个参数中的,不能完全利用kotlin编写lamdba的优势。

我们可以在此基础上定义个View的postDelayed的重载扩展函数,将Runnable放到方法参数的最后一个位置:
fun View.postDelayed(delayMillis: Long, runnable: Runnable) {
    postDelayed(runnable, delayMillis)
}

然后就可以这样使用:

mBinding.root.postDelayed(1000L) {
    println("size: ${mBinding.root.measuredHeight}")
}

3.dp与px之间快捷转换

平常我们会定义工具类方法实现dp和px之间的转换,这里我们以dp转px举例:

fun dp2px(dpValue: Float): Float {
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue,
    MainApp.mApplication.resources.displayMetrics)
}

//使用
val value = dp2px(10f)

这样使用起来还是不便捷,我们可以利用kotlin属性的getter进一步封装:

val Float.dp: Float
    get() = TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,
        this,
        MainApp.mApplication.resources.displayMetrics
    )

然后直接调用10f.dp就完成了10dp到px的转换

4.arrayOf、intArrayOf的区别使用

fun main() {
    val test1 = arrayOf(2, 4, 5)
    val tet2 = intArrayOf(4, 6, 7)
}

反编译成java代码:

public static final void main() {
   Integer[] var10000 = new Integer[]{2, 4, 5};
   int[] var2 = new int[]{4, 6, 7};
}

使用arrayOf的数组元素都使用的基本类型的包装类型,使用intArrayOf的数组元素则是使用的基本数据类型,减少了包装类带来的性能开销。

其他类型诸如float、byte等都和这个相同,所以大家平常编码构造基本数据类型数组时避免使用arrayOf,应选用对应的intArrayOf、byteArrayOf等等

阅读量:2022

点赞量:0

收藏量:0