适配器或视图保持器中的 Kotlin 合成

我是新来的。在我的 Activity类中,我发现并尝试使用合成方法而不是令人讨厌的方法 findViewById,但是我发现“如果我们想在 View 上调用合成属性(在适配器类中很有用) ,我们也应该导入 kotlinx.android.synthetic.main.View。*."但我不知道它到底是怎么工作的?有什么例子吗?

42874 次浏览

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.

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!

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.

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!"
}
}

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

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)
}

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.