Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Android-KTX

 Android-KTX

Small things to make our life easier

Rostyslav Lesovyi

August 27, 2019
Tweet

More Decks by Rostyslav Lesovyi

Other Decks in Programming

Transcript

  1. +
    Android-KTX
    Small things to make our life easier

    View Slide

  2. +
    Rostyslav Lesovyi

    View Slide

  3. +
    Android-KTX ➙ Core KTX
    ➙ Activity KTX
    ➙ Fragment KTX
    ➙ ViewModel KTX
    ➙ Reactive Streams KTX

    View Slide

  4. +
    What and why?
    sharedPreferences.edit()
    .putString("key", "value")
    .apply()
    sharedPreferences.edit {
    putString("key", "value")
    }
    handler.postDelayed({
    // do something
    }, 100)
    handler.postDelayed(100) {
    // do something
    }

    View Slide

  5. +
    Android-KTX Libraries
    Core KTX
    androidx.core.graphics
    androidx.core.view
    androidx.core.text
    …8 more...
    Fragment KTX
    Palette KTX
    SQLite KTX
    Collection KTX
    ViewModel KTX
    Reactive
    Streams KTX
    Navigation KTX
    WorkManager
    KTX

    View Slide

  6. +
    Core KTX
    androidx.core:core-ktx

    View Slide

  7. +
    Core KTX - androidx.core.animation
    animator.addListener(object : AnimatorListenerAdapter() {
    override fun onAnimationEnd(animation: Animator) {
    // finished
    }
    })
    animator.doOnStart {
    // finished
    }
    animator.doOnCancel {
    // cancelled
    }
    animator.doOnEnd {
    // ended
    }

    View Slide

  8. +
    Core KTX - androidx.core.content
    val array = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView)
    text = array.getString(R.styleable.MyCustomView_someAttr)
    array.recycle()
    context.withStyledAttributes(attrs, R.styleable.MyCustomView) {
    text = getString(R.styleable.MyCustomView_someAttr)
    }

    View Slide

  9. +
    Core KTX - androidx.core.content
    var wifiManager: WifiManager?
    // From Android 1 :)
    wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
    // From Android 23 (Marshmallow)
    wifiManager = context.getSystemService(WifiManager::class.java)
    // KTX
    wifiManager = context.getSystemService()

    View Slide

  10. +
    Core KTX - androidx.core.util
    val placeholder = createBitmap(1, 1)
    lruCache(
    maxSize = 10,
    sizeOf = { key, value -> key.length + value.byteCount },
    create = { placeholder },
    onEntryRemoved = { _, _, bitmap, _ -> bitmap.recycle() })

    View Slide

  11. +
    Core KTX - androidx.core.util
    val array = SparseArray()
    val value = array[42]
    array[42] = "abc"
    42 in array
    array.containsKey(42)
    array.containsValue("abc")
    array.getOrElse(42) { "abc" }
    array.forEach { key, value -> ... }

    View Slide

  12. +
    Core KTX - androidx.core.graphics
    val color = Color.CYAN
    val a = (color shr 24) and 0xff
    val r = (color shr 16) and 0xff
    val g = (color shr 8) and 0xff
    val b = color and 0xff
    val color = Color.CYAN
    val a = color.alpha
    val r = color.red
    val g = color.green
    val b = color.blue

    View Slide

  13. +
    Core KTX - androidx.core.graphics
    canvas.save()
    canvas.translate(10f, 10f)
    canvas.drawRect(0f, 0f, 20f, 20f, paint)
    canvas.restore()
    canvas.withTranslation(x = 10f, y = 10f) {
    drawRect(0f, 0f, 20f, 20f, paint)
    }

    View Slide

  14. +
    Core KTX - androidx.core.graphics.drawable
    val bounds = drawable.bounds
    drawable.setBounds(10, bounds.top, bounds.right, bounds.bottom)
    drawable.updateBounds(left = 10)
    val bitmap = drawable.toBitmap()

    View Slide

  15. +
    Core KTX - androidx.core.os
    TraceCompat.beginSection("my_trace_tag")
    // some stuff to benchmark
    TraceCompat.endSection()
    trace("my_trace_tag") {
    // some stuff to benchmark
    }

    View Slide

  16. +
    Core KTX - androidx.core.os
    val bundle = Bundle()
    bundle.putInt("key1", 42)
    bundle.putString("key2", "my string")
    val bundle = bundleOf(
    "key1" to 42,
    "key2" to "my string")
    Performance warning

    View Slide

  17. +
    Core KTX - androidx.core.os (bundleOf)
    fun bundleOf(vararg pairs: Pair) = Bundle(pairs.size).apply {
    for ((key, value) in pairs) {
    when (value) {
    null -> putString(key, null) // Any nullable type will suffice.
    // Scalars
    is Boolean -> putBoolean(key, value)
    is Byte -> putByte(key, value)
    is Char -> putChar(key, value)
    is Double -> putDouble(key, value)
    is Float -> putFloat(key, value)
    ...

    View Slide

  18. +
    Core KTX - androidx.core.os
    handler.postDelayed({
    // do something
    }, delay)
    handler.postDelayed(delay) {
    // do something
    }
    handler.postAtTime({
    // do something
    }, time)
    handler.postAtTime(time) {
    // do something
    }

    View Slide

  19. +
    Core KTX - androidx.core.text
    val string = " abc "
    val len = string.trim().length
    val len = string.trimmedLength()
    Bad
    Good

    View Slide

  20. +
    Core KTX - androidx.core.text
    Color
    Italic
    Bold
    Red fox jumped over the lazy dog

    View Slide

  21. +
    Core KTX - androidx.core.text
    val sb = SpannableString("Red fox jumped over the lazy dog")
    sb.setSpan(ForegroundColorSpan(Color.RED), 0, 3, 0)
    sb.setSpan(StyleSpan(Typeface.ITALIC), 8, 14, 0)
    sb.setSpan(StyleSpan(Typeface.BOLD), 24, 28, 0)
    Red fox jumped over the lazy dog
    Bad

    View Slide

  22. +
    Core KTX - androidx.core.text
    fun SpannableStringBuilder.append(text: CharSequence, span: Any) = apply {
    val len1 = length
    append(text)
    val len2 = length
    setSpan(span, len1, len2, 0)
    }
    Red fox jumped over the lazy dog
    Better

    View Slide

  23. +
    Core KTX - androidx.core.text
    val sb = SpannableStringBuilder()
    .append("Red", ForegroundColorSpan(Color.RED))
    .append(" fox ")
    .append("jumped", StyleSpan(Typeface.ITALIC))
    .append(" over the ")
    .append("lazy", StyleSpan(Typeface.BOLD))
    .append(" dog")
    Red fox jumped over the lazy dog
    Better

    View Slide

  24. +
    Core KTX - androidx.core.text
    buildSpannedString {
    color(Color.RED) { append("Red") }
    append(" fox ")
    italic { append("jumped") }
    append(" over the ")
    bold { append("lazy") }
    append("dog")
    }
    Red fox jumped over the lazy dog
    Good

    View Slide

  25. +
    Core KTX - androidx.core.widget
    textView.doAfterTextChanged { text ->
    // do something
    }
    textView.doBeforeTextChanged { text, start, count, after ->
    // do something
    }
    textView.doOnTextChanged { text, start, count, after ->
    // do something
    }

    View Slide

  26. +
    Core KTX - androidx.core.view
    view.isGone = true
    view.isVisible = false
    view.isInvisible = true
    val start = view.marginStart
    val bottom = view.marginBottom
    view.updatePadding(left = 42)
    view.updatePaddingRelative(start = 42)
    view.postDelayed(100) { /* do something */ }
    val bitmap = view.drawToBitmap()

    View Slide

  27. +
    Core KTX - androidx.core.view
    val params = view.layoutParams as LinearLayout.LayoutParams
    params.weight = .42f
    view.layoutParams = params
    view.updateLayoutParams {
    weight = .42f
    }

    View Slide

  28. +
    Core KTX - androidx.core.view
    // instant or delayed
    view.doOnLayout {
    }
    // delayed
    view.doOnNextLayout {
    }
    // delayed, avoids memory leaks
    view.doOnPreDraw {
    }

    View Slide

  29. +
    Android - ViewTreeObserver risks
    View
    viewTreeObserver
    viewTreeObserver.addOnPreDrawListener(callback1)
    Detached

    View Slide

  30. +
    Android - ViewTreeObserver risks
    View
    viewTreeObserver
    > callback1
    Detached

    View Slide

  31. +
    Window
    viewTreeObserver
    Android - ViewTreeObserver risks
    Detached Detached
    Attached
    View
    viewTreeObserver
    > callback1
    Move callbacks

    View Slide

  32. +
    Window
    viewTreeObserver
    > callback1
    Android - ViewTreeObserver risks
    View
    viewTreeObserver
    View
    viewTreeObserver
    onAttachedToWindow
    onDetachedFromWindow
    Detached Detached
    Attached
    View
    viewTreeObserver

    View Slide

  33. +
    Android - ViewTreeObserver risks
    View
    viewTreeObserver
    Detached
    viewTreeObserver.removeOnPreDrawListener(callback1)

    View Slide

  34. +
    Activity KTX
    androidx.activity:activity-ktx

    View Slide

  35. +
    Activity KTX
    activity.onBackPressedDispatcher.addCallback(lifecycleOwner) {
    // do something on back press
    isEnabled = false
    }
    class MyActivity : AppCompatActivity() {
    private val viewModel1 by viewModels()
    }

    View Slide

  36. +
    Fragment KTX
    androidx.fragment:fragment-ktx

    View Slide

  37. +
    Fragment KTX
    fragmentManager.commit(allowStateLoss = true) {
    add(MyFragment(), "my_tag")
    }
    class MyFragment : Fragment() {
    private val viewModel1 by viewModels()
    private val viewModel2 by activityViewModels()
    }

    View Slide

  38. +
    ViewModel KTX
    androidx.lifecycle:lifecycle-viewmodel-ktx

    View Slide

  39. +
    ViewModel KTX
    class MyViewModel : ViewModel(), CoroutineScope {
    private val job = SupervisorJob()
    override val coroutineContext = job + Dispatchers.Main
    override fun onCleared() {
    super.onCleared()
    job.cancel()
    }
    fun doWork() = launch {
    // main thread coroutine
    }
    }

    View Slide

  40. +
    ViewModel KTX
    class MyViewModel : ViewModel() {
    fun doWork() = viewModelScope.launch {
    // main thread coroutine
    }
    }

    View Slide

  41. +
    Reactive Streams KTX
    androidx.lifecycle:lifecycle-reactivestreams-ktx

    View Slide

  42. +
    Reactive Streams KTX
    val source: Publisher = ...
    val liveData: LiveData = source.toLiveData()
    val publisher: Publisher = liveData.toPublisher(lifecycleOwner)

    View Slide

  43. +
    More info:
    https://developer.android.com/kotlin/ktx

    View Slide

  44. +
    Q&A

    View Slide