Kotlin synthetic in Adapter or ViewHolder

KotlinKotlin Android-Extensions

Kotlin Problem Overview


I am new in kotlin. I have found and tried to use synthetic method instead of annoying method findViewById in my Activity class, but I have found "If we want to call the synthetic properties on View (useful in adapter classes), we should also import kotlinx.android.synthetic.main.view.*." But I can't figure out how it exactly works? Is there any examples?

Kotlin Solutions


Solution 1 - Kotlin

Simple example from https://github.com/antoniolg/Kotlin-for-Android-Developers

import kotlinx.android.synthetic.item_forecast.view.*

class ForecastListAdapter() : RecyclerView.Adapter<ForecastListAdapter.ViewHolder>() {

    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {

        fun bindForecast(forecast: Forecast) {
            itemView.date.text = forecast.date.toDateString()
        }
    }
}

No need to write

val view = itemView.findViewById(R.id.date) as TextView
view.text = forecast.date.toDateString()

Just

itemView.date.text = forecast.date.toDateString()

Simple and effective!

Solution 2 - Kotlin

Kotling 1.1.4 out

Further information : https://antonioleiva.com/kotlin-android-extensions/

You need to enable Kotlin Android Extentions by adding this to your build.gradle:

apply plugin: 'org.jetbrains.kotlin.android.extensions'
androidExtensions {
    experimental = true
}

Since this new version of Kotlin, the Android Extensions have incorporated some new interesting features: caches in any class (which interestingly includes ViewHolder)

Using it on a ViewHolder (or any custom class). Note that this class should implement LayoutContainer interface:

class ViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView), 
        LayoutContainer {
 
    fun bind(title: String) {
        itemTitle.text = "Hello Kotlin!"
    }
}

Solution 3 - Kotlin

You need

import kotlinx.android.synthetic.row_wall.view.*

And later something along the lines of:

convertView.titleText.text = item.title

The point is that the view.* introduces extensions to the View class.

Solution 4 - Kotlin

Try

class CustomViewModel(val baseView: View) {
    val firstName = baseView.firstName
    val lastName = baseView.lastName
}

View object exposes the views ref:https://discuss.kotlinlang.org/t/unable-to-use-kotlin-android-extension-in-adapter-class/2890

Solution 5 - Kotlin

If you are using the latest version l;.you don't have to add experimental = true to it.

in Project level Gradle

classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.21'

And in app level Gradle

apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions' //These should be on the top of file.

and in dependencies..

implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21'

and import below as

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

and example

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

class AnimalVH(parent: ViewGroup, layoutID: Int) : BaseViewHolder<Animal>(parent, layoutID) {

    override fun bindData(animal: Animal) {
        itemView.tv_animal.text = animal.title
    }
}

where BaseViewHolder is

abstract class BaseViewHolder<T>(parent: ViewGroup, layoutID: Int) : RecyclerView.ViewHolder(
    LayoutInflater.from(parent.context).inflate(layoutID, parent, false)
) {
    abstract fun bindData(model: T)
}

Solution 6 - Kotlin

It means you have to place this line at the beginning of your source file:

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

So now instead of, for example, findView(R.id.textView) as TextView you would write just textView. The latter is a synthetic extension property located in the package kotlinx.android.synthetic.main.view, that's why you have to import everything from it.

There's a tutorial on the official site, take a look.

Solution 7 - Kotlin

FYI: Data binding is recommended over synthetic for view lookups.

Comment from a DA for Android from Google on Reddit

> Hey! Developer Advocate for Android at Google here! > > I wanted to add a bit of background here. Kotlin Extensions with > synthetic views was never intentionally “recommended” though that > shouldn’t be taken as a recommendation to not use them. If they're > working for you please feel free to continue using them in your app! > > We’ve been shifting away from them (e.g. we don’t teach them in the > Udacity course) because they expose a global namespace of ids that’s > unrelated to the layout that’s actually inflated with no checks > against invalid lookups, are Kotlin only, and don't expose nullability > when views are only present in some configuration. All together, these > issues cause the API to increase number of crashes for Android apps. > > On the other hand, they do offer a lightweight API that can help > simplify view lookups. In this space it's also worth taking a look at > Data Binding which also does automatic view lookups - as well as > integrates with LiveData to automatically update your views as data > changes. > > Today, there's a few options in this space that work: > > Data Binding is the recommendation for view lookup as well as binding, > but it does add a bit of overhead when compared to Android Kotlin > Extensions. It's worth taking a look to see if this is a good fit for > your app. Data Binding also allows you to observe LiveData to bind > views automatically when data changes. Compared to Kotlin Extensions, > it adds compile time checking of view lookups and type safety. Android > Kotlin Extensions is not officially recommended (which is not the same > as recommendation against). It does come with the issues mentioned > above, so for our code we're not using them. Butter Knife is another > solution that is extremely popular and works for both Kotlin and the > Java Programming Language. Reading through the comments here there's a > lot of developers that are having great luck with Kotlin Extensions. > That's great - and something we'll keep in mind as we look at ways to > continue improving our APIs. If you haven't taken a look at Data > Binding, definitely give it a shot. > > As an aside, our internal code style guide is not intended to be > directly applied outside of our codebase. For example, we use > mPrefixVariables, but there's no reason that every app should follow > that style.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbusyleeView Question on Stackoverflow
Solution 1 - KotlinPeter ZhaoView Answer on Stackoverflow
Solution 2 - KotlinDhaval JivaniView Answer on Stackoverflow
Solution 3 - KotlinZsolt SzatmariView Answer on Stackoverflow
Solution 4 - KotlinhyenaView Answer on Stackoverflow
Solution 5 - KotlinZar E AhmerView Answer on Stackoverflow
Solution 6 - KotlinAlexander UdalovView Answer on Stackoverflow
Solution 7 - Kotlinuser158View Answer on Stackoverflow