Make writing a habit together! This is my first day to participate in the “Gold Digging Day New Plan · April More text challenge”, click to see the details of the activity.

This article focuses on the techniques Kotlin uses in project development

1. Use lazy delegates correctly

In everyday development, people use lazy loading directly like this:

val vm: String by lazy { "" }
Copy the code

This is done with locks by default and is fine in concurrent environments, but can cause performance overhead in non-concurrent environments such as the Android main thread.

Lazy implementation:

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)
    }
Copy the code

Lazy lazy loading support three patterns: LazyThreadSafetyMode SYNCHRONIZED: adding synchronization locks, delay the lazy initialization thread-safe

LazyThreadSafetyMode. PUBLICATION: the initialization of lambda expressions can be called multiple times at the same time, but only the first return value as the initialization values

LazyThreadSafetyMode. NONE: not lock, not thread-safe

Therefore, we can re-wrap the lazy, exposing thread-safe lazy and unsafe lazy, and select the corresponding method call according to the specific usage scenario

// Thread safety
fun <T> safeLazy(initializer: () -> T): Lazy<T> =
    lazy(LazyThreadSafetyMode.SYNCHRONIZED, initializer)

// Not thread safe
fun <T> unSafeLazy(initializer: () -> T): Lazy<T> =
    lazy(LazyThreadSafetyMode.NONE, initializer)
Copy the code

2.View.postDelay()Optimizing the use

PostDelay () is used to obtain the width and height of the View, and can be used in onResume to roughly estimate the interface drawing time:

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

But this native postDelayed was particularly awkward to write because its Runnable was placed in the first parameter and did not take full advantage of kotlin’s lamdba writing.

We can then define a postDelayed View overloaded extension function that puts Runnable in the last position of the method argument:

fun View.postDelayed(delayMillis: Long, runnable: Runnable) {
    postDelayed(runnable, delayMillis)
}
Copy the code

It can then be used like this:

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

3. Quick conversion between DP and PX

We usually define a utility class method to convert dp to px. Here we use dp to px as an example:

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

/ / use
val value = dp2px(10f)
Copy the code

This is still not convenient to use, we can use the getter of the Kotlin attribute to further encapsulate:

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

Then call 10F.dp directly to complete the 10DP to PX conversion

4. Different uses of arrayOf and intArrayOf

fun main(a) {
    val test1 = arrayOf(2.4.5)
    val tet2 = intArrayOf(4.6.7)}Copy the code

Decompiling into Java code:

public static final void main(a) {
   Integer[] var10000 = new Integer[]{2.4.5};
   int[] var2 = new int[] {4.6.7};
}
Copy the code

Array elements using arrayOf are the basic data types used, reducing the performance overhead of wrapping classes. Other types, such as float, byte, and so on, are the same, so avoid arrayOf when constructing arrays of primitive data types. Instead, use the corresponding intArrayOf, byteArrayOf, and so on