AdapterまたはViewHolderで合成されたKotlin


84

私はkotlinが初めてです。私が発見し、代わりに迷惑な方法の合成方法を使用しようとしましたfindViewById、私の中でActivityクラスが、我々は(アダプタクラスで有用)ビューの合成のプロパティを呼び出したい場合は、私が」発見した、我々はまた、kotlinx.android.synthetic.mainインポートする必要があります。見る。*。" しかし、私はそれが正確にどのように機能するのか理解できませんか?例はありますか?


このブログまたはこの例を
Cabezas 2018年

回答:


96

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

書く必要はありません

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

ただ

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

シンプルで効果的!


4
わかりました、これはばかげた質問かもしれませんが、「itemView」参照はどこから来ていますか?
Saulo Aguiar 2016

4
ビュー拡張機能のキャッシュはないため、通常のviewHolderと同様に、ビューへの参照をキャッシュする必要があります。
miha_x64 2017年

21
残念ながら、それは各bind()呼び出しでfindViewByIdを
Miguel Beltran

2
@Mike Kotlin 1.1.4以降、すべてのビューがキャッシュされます。ViewHoldersでも。あなたが投稿した記事はこれについても言及しています。
Stefan Medack 2017年

2
@StefanMedack私は記事の著者です:)これは実験的な機能の一部にすぎず、手動で有効にする必要があることを指摘する必要があります。まだ試していません。
ミゲルベルトラン2017年

37

コトリング1.1.4アウト

詳細情報:https//antonioleiva.com/kotlin-android-extensions/

これをbuild.gradleに追加して、Kotlin AndroidExtentionsを有効にする必要があります

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

Kotlinのこの新しいバージョン以降、Android拡張機能にはいくつかの新しい興味深い機能が組み込まれています。任意のクラスのキャッシュ(興味深いことにViewHolderが含まれています)

ViewHolder(または任意のカスタムクラス)で使用します。このクラスはLayoutContainerインターフェースを実装する必要があることに注意してください。

class ViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView), 
        LayoutContainer {

    fun bind(title: String) {
        itemTitle.text = "Hello Kotlin!"
    }
}

3
この情報への追加:Kotlin 1.1.4によると、この機能は実験的なものであり、build.gradleファイルで有効にする必要があります
Miguel Beltran 2017年

2
これはもう実験的ですか?これを本番コードで使用したい
Carson Holzheimer 2018年

@CarsonH​​olzheimerこの機能はまだ実験
段階です

でも動作しないよう1.3.21です。彼らはそれを実装するつもりはないと思います
user9 2419

しかし、使用することはできcontainerView.itemTitle.text = "Hello Kotlin!"
それで

11

あなたが必要

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

そして後で次の線に沿った何か:

convertView.titleText.text = item.title

重要なのは、view。*がViewクラスに拡張機能を導入することです。


1
答えはすでにstackoverflow.com/a/33428208/7767664に与えられましたなぜあなたはそれを繰り返したのですか?
user9 2419

8

試してみてください

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

ビューオブジェクトはビューを公開しますref:https//discuss.kotlinlang.org/t/unable-to-use-kotlin-android-extension-in-adapter-class/2890


答えはすでにstackoverflow.com/a/33428208/7767664に与えられましたなぜあなたはそれを繰り返したのですか?
user9 2419

@ user924。答えは別のスレッドに既にある場合は、中等度および重複として、現在のスレッドをマークし、他のスレッドへの参照を追加してください
ハイエナ

4

最新バージョンl;を使用している場合は、experimental = trueを追加する必要はありません。

プロジェクトレベルのGradleで

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

そしてアプリレベルのGradle

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

と依存関係で。

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

以下のようにインポートします

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

と例

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

BaseViewHolderは

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

これについての公式の確認はありますか?.view.*インポートを使用すると目的が損なわれると思います。フォールバックはfindViewById<>、毎回、パターンViewHolderそのものを思いとどまらせることです。
スカイネット


1

これは、ソースファイルの先頭に次の行を配置する必要があることを意味します。

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

だから今、例えばの代わりに、findView(R.id.textView) as TextViewあなたはただ書くでしょうtextViewます。後者は、パッケージに含まれる合成拡張プロパティです。kotlinx.android.synthetic.main.viewにそこからすべてをインポートする必要があります。

公式サイトにチュートリアルがありますので、ご覧ください。


1
私はまだそれを見ました。上で説明したように、私は自分の活動のためにそれをしました。しかし、BaseAdapter派生物内でどのように使用できますか?
busylee

1
さて、基本的findViewById()にはView、のように、でメソッドを呼び出すことができますholder.findViewById(R.id.name)。Kotlin Android Extensionsを使用すると、ただ書くことができますholder.name。このコードは内部で書かれているとgetView()機能:val base = inflater.inflate(R.layout.list_item, parent, false) base.name.text = "John Smith"
yanex

しかし、さまざまなレイアウトの複数のビューホルダーを使用する必要がある場合はどうなりますか?どうすれば合成でそれを実現できますか?レイアウトごとに特定の「合成リンク」を使用する必要があり、IDが類似しているレイアウトがいくつかあるためです。
Natan Rubinstein

0

ご参考までに:ビュールックアップには、合成よりもデータバインディングをお勧めします。

Reddit上のGoogleのAndroid用DAからのコメント

ねえ!ここGoogleでAndroidの開発者擁護者!

ここに少し背景を追加したいと思いました。合成ビューを備えたKotlin拡張機能は、意図的に「推奨」されることはありませんでしたが、使用しないことを推奨するものではありません。彼らがあなたのために働いているなら、あなたのアプリでそれらを使い続けてください!

無効なルックアップに対するチェックなしで実際に拡張されたレイアウトとは関係のないIDのグローバル名前空間を公開し、Kotlinのみであり、ビューが一部の構成にのみ存在する場合は、null可能性を公開しません。これらの問題により、APIはAndroidアプリのクラッシュ数を増加させます。

一方、ビューのルックアップを簡素化するのに役立つ軽量のAPIを提供します。このスペースでは、自動ビュールックアップも実行するデータバインディングを確認する価値があります。また、LiveDataと統合して、データの変更に応じてビューを自動的に更新します。

今日、このスペースで機能するいくつかのオプションがあります。

データバインディングは、ビュールックアップとバインディングの推奨事項ですが、Android Kotlin Extensionsと比較すると、多少のオーバーヘッドが追加されます。これがアプリに適しているかどうかを確認する価値があります。データバインディングを使用すると、LiveDataを監視して、データが変更されたときにビューを自動的にバインドすることもできます。Kotlin Extensionsと比較して、ビュールックアップとタイプセーフティのコンパイル時チェックが追加されています。Android Kotlin Extensionsは公式には推奨されていません(これは推奨と同じではありません)。上記の問題が発生するため、コードでは使用していません。バターナイフは非常に人気のある別のソリューションであり、KotlinとJavaプログラミング言語の両方で機能します。ここのコメントを読んでください KotlinExtensionsで幸運を祈っている多くの開発者。これはすばらしいことです。APIを継続的に改善する方法を検討する際に留意する必要があります。データバインディングをまだ見ていない場合は、ぜひ試してみてください。

余談ですが、内部コードスタイルガイドは、コードベースの外部に直接適用することを意図したものではありません。たとえば、mPrefixVariablesを使用しますが、すべてのアプリがそのスタイルに従う必要がある理由はありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.