44

ViewBinding を使い始めました。すべての子のレイアウトに存在すると予想されるビューで同じロジックを処理する必要がある抽象基本クラスで ViewBinding を使用する方法の例またはアドバイスを検索した後、この質問をここに投稿することになります。

シナリオ:
基本クラスがありpublic abstract class BaseFragmentます。この基本クラスを拡張するフラグメントが複数あります。これらのフラグメントには、基本クラスの実装から処理される共通のビューがあります ("old" を使用findViewById())。たとえば、すべてのフラグメントのレイアウトには、ID が text_title の TextView が含まれていることが期待されます。からの処理方法は次BaseFragmentonViewCreated()とおりです。

TextView title = view.findViewById(R.id.text_title);
// Do something with the view from the base class

ViewBinding-API は、子フラグメントごとにバインディング クラスを生成するようになりました。バインディングを使用してビューを参照できます。しかし、基本クラスの具象バインディングを使用することはできません。基本クラスにジェネリックを導入しても、フラグメント バインディングの種類が多すぎるため、このソリューションは今のところ破棄しました。

抽象基本クラスからバインディングのビューを処理するための推奨される方法は何ですか? ベストプラクティスはありますか? このシナリオをエレガントな方法で処理するための組み込みメカニズムが API に見つかりませんでした。

子フラグメントに共通のビューが含まれていると予想される場合、フラグメントの具体的なバインディングからビューを返し、基本クラスからアクセスできるようにする抽象メソッドを提供できます。(たとえばprotected abstract TextView getTitleView();)。しかし、これは使用するよりも利点findViewById()ですか? どう思いますか?他の(より良い)解決策はありますか?議論を始めましょう。

4

9 に答える 9

0
inline fun <reified BindingT : ViewBinding> AppCompatActivity.viewBindings(
    crossinline bind: (View) -> BindingT
) = object : Lazy<BindingT> {

    private var initialized: BindingT? = null

    override val value: BindingT
        get() = initialized ?: bind(
            findViewById<ViewGroup>(android.R.id.content).getChildAt(0)
        ).also {
            initialized = it
        }

    override fun isInitialized() = initialized != null
}

于 2021-05-04T08:28:49.610 に答える
0

bind共通クラスのメソッドを使うのが簡単な対応だと思います。

これがすべてのケースで機能するとは限りませんが、同様の要素を持つビューでは機能します。

2 つのレイアウトがrow_type_1.xmlありrow_type_2.xml、それらが共通の要素を共有している場合、次のようにすることができます。

ROW_TYPE_1 -> CommonRowViewHolder(
                    RowType1Binding.inflate(LayoutInflater.from(parent.context), parent, false))

次に、タイプ 2 の場合、独自の Binding クラスを受け取る別の ViewHolder を作成する代わりに、次のようにします。

ROW_TYPE_2 -> {
    val type2Binding = RowType2Binding.inflate(LayoutInflater.from(parent.context), parent, false))
    CommonRowViewHolder(RowType1Binding.bind(type2Binding))
}

代わりにそれがコンポーネントのサブセットである場合、継承を配置できます

CommonRowViewHolder: ViewHolder {
    fun bind(binding: RowType1Holder)
}

Type2RowViewHolder: CommonRowViewHolder {

    fun bind(binding: RowType2Holder) {
        super.bind(Type1RowViewHolder.bind(binding))
        
        //perform specific views for type 2 binding ...
    }
}
于 2021-05-03T19:01:09.180 に答える