私は最善の方法を見つけようとしていますAndroid Kotlinのビューバインディング。そこにはいくつかのオプションがあるようです。
findViewById
val button: Button by lazy { findViewById<Button>(R.id.button) }
バターナイフ
https://github.com/JakeWharton/butterknife
@BindView(R.id.button) lateinit var button: Button
Kotlin Android Extensions
https://kotlinlang.org/docs/tutorials/Android-plugin.html
import kotlinx.Android.synthetic.main.activity_main.*
私はJava landのfindViewByIdとButterknifeにかなり精通していますが、Kotlinの各ビューバインディングアプローチの長所と短所は何ですか?
Kotlin Android Extensionsは、RecyclerView + ViewHolderパターンでうまく機能しますか?
また、Kotlin Android拡張機能は、include
を介してネストされたビューのビューバインディングを処理しますか?
例:activity_main.xml
を使用するアクティビティの場合、View custom1
にどのようにアクセスしますか?
activity_main.xml
<...>
<include layout="@layout/custom" Android:id="@+id/custom" />
</>
custom.xml
<...>
<View Android:id="@+id/custom1" ... />
<View Android:id="@+id/custom2" ... />
</>
_kotlin-Android-extensions
_はKotlin
に適しています。 ButterKnifeも優れていますが、ここでは_kotlin-Android-extensions
_の方が賢明な選択です。
理由:Kotlin
はsynthetic
プロパティを使用し、_caching function
_を使用してオンデマンドで呼び出されますButterKnife
は、ButterKnife.bind()
(少し時間がかかる)で一度にすべてのビューをバインドしますが、アクティビティ/フラグメントの読み込み)。 Kotlin
を使用すると、ビューをバインドするために注釈を使用する必要さえありません。
はい、RecyclerView + ViewHolderパターンとも良好に動作します。インポートする必要があるのは、_kotlinx.Android.synthetic.main.layout_main.view.*
_(if _layout_main.xml
_がアクティビティ/フラグメントレイアウトファイル名の場合)です。
include
を使用してインポートされたレイアウトに対して、追加の作業を行う必要はありません。インポートされたビューのIDを使用するだけです。
次の公式ドキュメントノートをご覧ください。
Kotlin Android ExtensionsはKotlinコンパイラのプラグインであり、次の2つのことを行います。
- 各Kotlinアクティビティ内に非表示のキャッシュ機能とフィールドを追加します。メソッドは非常に小さいため、APKのサイズはあまり増加しません。
各合成プロパティ呼び出しを関数呼び出しに置き換えます。
これがどのように機能するかは、レシーバーがモジュールソースにあるKotlin Activity/Fragmentクラスである合成プロパティを呼び出すときに、キャッシュ機能が呼び出されることです。たとえば、与えられた
_class MyActivity : Activity()
fun MyActivity.a() {
this.textView.setText(“”)
}
_
myActivity内に非表示のキャッシュ関数が生成されるため、キャッシュメカニズムを使用できます。
ただし、次の場合:
_fun Activity.b() {
this.textView.setText(“”)
}
_
この関数がソースからのアクティビティのみで呼び出されるのか、プレーンJavaアクティビティでも呼び出されるのかどうかはわかりません。そのため、MyActivityインスタンスが前の例はレシーバーです。
上記へのリンク ドキュメントページ
役に立てば幸いです。
使用の世話をする
val button: Button by lazy { findViewById<Button>(R.id.button) }
ビューが破壊されたときに問題にすでに直面していますが、フラグメントのインスタンスが生き残ると(アクティビティの場合は適用されないと思います)、古いものを参照するlazyプロパティを保持しますビュー。
例:
レイアウトに静的な値がある場合、Android:text="foo"
//calling first time
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
button.setText("bar")
// button is called for the first time,
// then button is the view created recently and shows "bar"
}
次に、フラグメントを置き換えるためにフラグメントが破棄されますが、それからカムバックし、再度onCreateViewコールインを再生成しました。
//calling second after destroyed
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
button.setText(Date().time.toString())
//button is already set, then you are setting the value the to old view reference
// and in your new button the value won't be assigned
// The text showed in the button will be "foo"
}
この質問を重複としてフラグすることはできません。異なる質問の下で回答/議論された複数のことを尋ねているからです。
Kotlinの各ビューバインディングアプローチの長所と短所は何ですか?
これは議論されました here 。
Kotlin Android拡張機能はincludeを介してネストされたビューのビューバインディングを処理しますか?例:activity_main.xmlを使用するアクティビティの場合、View custom1はどのようにアクセスされますか?
Kotlin Android ExtensionsはfindViewById
を呼び出すだけです。 here を参照してください。
Kotlin Android Extensionsは、RecyclerView + ViewHolderパターンでうまく機能しますか?
はい、そうです。ただし、アクティビティやフラグメントなどのキャッシュは存在しないため、そこから取得したビューをプロパティに保存する必要があります。 here を参照してください。
未回答の質問がある場合は、お気軽に質問してください。
dataindingライブラリを使用している場合。ビューバインディングをデータバインディングする必要があります。
それはkotlin-extensionsよりも明示的であるため
p.s findviewbyidは非常に不便で定型的なコードです
4番目のオプションがあり、これはView Binding と呼ばれます、 Android Studio 3.6 Carnary 11で利用可能
バインディングの表示
ビューバインディングは、ビューと対話するコードをより簡単に記述できる機能です。モジュールでビューバインディングを有効にすると、そのモジュールに存在する各XMLレイアウトファイルのバインディングクラスが生成されます。バインディングクラスのインスタンスには、対応するレイアウトのIDを持つすべてのビューへの直接参照が含まれます。
ほとんどの場合、ビューバインディングは
findViewById
を置き換えます。
findViewById
との違いビューバインディングには、findViewByIdを使用するよりも重要な利点があります。
ヌルの安全性:ビューのバインディングはビューへの直接参照を作成するため、無効なビューIDによるヌルポインター例外のリスクはありません。さらに、ビューがレイアウトの一部の構成にのみ存在する場合、バインディングクラスでその参照を含むフィールドは_
@Nullable
_でマークされます。タイプセーフティ:各バインディングクラスのフィールドには、XMLファイルで参照するビューと一致するタイプがあります。これは、クラスキャスト例外のリスクがないことを意味します。
データバインディングライブラリとの違い
ビューバインディングとデータバインディングライブラリはどちらも、ビューを直接参照するために使用できるバインディングクラスを生成します。ただし、顕著な違いがあります。
- データバインディングライブラリは、_
<layout>
_タグを使用して作成されたデータバインディングレイアウトのみを処理します。- ビューバインディングはレイアウト変数またはレイアウト式をサポートしていないため、レイアウトをXMLのデータにバインドするために使用できません。
使用法
プロジェクトのモジュールでビューバインディングを利用するには、_
build.gradle
_ファイルに次の行を追加します。_Android { viewBinding.enabled = true }
_たとえば、_
result_profile.xml
_というレイアウトファイルがある場合:_<LinearLayout ... > <TextView Android:id="@+id/name" /> <ImageView Android:cropToPadding="true" /> <Button Android:id="@+id/button" Android:background="@drawable/rounded_button" /> </LinearLayout>
_この例では、
activity
でResultProfileBinding.inflate()
を呼び出すことができます。_private lateinit var binding: ResultProfileBinding @Override fun onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) binding = ResultProfileBinding.inflate(layoutInflater) setContentView(binding.root) }
_バインディングクラスのインスタンスを使用して、任意のビューを参照できるようになりました。
_binding.name.text = viewModel.name binding.button.setOnClickListener { viewModel.userClicked() }
_