Skip to content

5.) Android Specific Stuff

Gabor Varadi edited this page Feb 14, 2021 · 6 revisions

synthetic view accessors with kotlin android extensions

With the kotlin-android-extensions plugin on Android, you can generate "synthetic accessors" that can replace calls to findViewById, or using the @BindView(R.id.*) from ButterKnife.

apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

Then we can use synthetics. Please note that synthetic imports use the view IDs directly instead of making them camelCase, so unless you're ok with your variable names having _s in them, it's generally recommended to use camelCase IDs for Android views (if you are using Kotlin synthetics).

<LinearLayout
    android:id="@+id/containerMyViews"
    ...
    android:visibility="gone">
    ...
</LinearLayout>

and

import kotlinx.android.synthetic.main.my_layout.view.*

class MyActivity: AppCompatActivity() {
    fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.my_layout)

        containerMyViews.show() // you can access views like this
    }
}

Please note that it calls findViewById again and again, in which case you might want to use the LayoutContainer interface (which is experimental), that lets you instruct synthetics to cache views. This is typically better performance for ViewHolder.

Kotlin synthetic view accessors are deprecated, and should be replaced with ViewBinding instead.

buildFeatures {
    viewBinding true
}

Then use as follows

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    val binding = MyFragmentBinding.bind(view)
    with(binding) {
        // use like synthetics
    }
}

@Parcelize data class with experimental kotlin android extensions (or kotlin-parcelize since 1.4.20)

A rather powerful Kotlin feature is the support for @Parcelize, which makes Kotlin automatically generate the Parcelable implementation for a class; this is very powerful in conjunction with data classes.

You must enable experimental features:

androidExtensions { // if using the deprecated `kotlin-android-extensions`
    experimental = true
}

And then for example,

import kotlinx.parcelize.Parcelize

@Parcelize
data class PlantDetailsKey(val plantId: String) : BaseKey(), Parcelable {
    override fun createFragment() = PlantDetailsFragment()
}

Any variables or values given to the class in its primary constructor are parcelled and restored by the implementation.

What's worth noting is that it is possible to customize behavior if our companion object implements the Parceler<T> interface.

The CREATOR however currently is tricky to access (even though it is needed for writeTypedList), you have to access it from Java, and expose it to Kotlin (or use reflection).

Clone this wiki locally