2017-12-26 13 views
0

Kotlin Android拡張機能は、アクティビティ/フラグメント/アダプタでIDを直接使用する方法を提供します。 だから私は、アダプタの一般的な方法をして、アダプタの代わりにアダプタのユーザにバインドビューの責任を任せています。たとえば :私はちょうど私が好きなすべての単一のレイアウトを持つファイルおよびアダプタの同じコードを書き換えることなく、アダプタをバインドするために、レイアウトファイルとバインド機能を渡すことができKotlin Android Extensionを使用してアダプタのビューバインディングを延期することはできますか

class GenericAdapter<T>(
    @LayoutRes private val layoutId: Int, 
    private var list: List<T>, 
    inline private val bind: (View, T, Int) -> Unit) : RecyclerView.Adapter<InnerHolder>() { 
    override fun onBindViewHolder(holder: InnerHolder?, position: Int) { 
     holder?.containerView?.let { 
      bind(holder.containerView, list[position], position) 
     } 
    } 

    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): InnerHolder = 
     InnerHolder(LayoutInflater.from(parent?.context).inflate(layoutId, 
      parent, 
      false)) 

    override fun getItemCount(): Int = list.size 

    class InnerHolder(
     val containerView: View?) : RecyclerView.ViewHolder(containerView) 

} 

しかし、ここに問題があります: ViewHolderパターンは、ChildViewが膨らんだたびに「findViewById」という呼び出しを取り除きたいです。しかし、アダプターの私の実装で。アダプターがビューをバインドするたびに、「findViewById」を呼び出す必要があります。

編集:「キャッシュ」問題の詳細。

アクティビティでGenericAdapterを使用する。同様

override fun onCreated(savedInstanceState: Bundle?){ 
    list.adapter = GenericAdapter<Item>(items){ view,item,position -> 
     view.textview.text = item.text 
    } 
} 

が、これは、このに逆コンパイルします:

 TextView var2 = (TextView)var10000.findViewById(id.textview); 
    Intrinsics.checkExpressionValueIsNotNull(var2, "itemView.tv_text"); 
    var2.setText((CharSequence)String.valueOf(var1)); 

しかし、彼らは、例えばLayoutContainerとAndroidの拡張子を持つ実験的なツールを持っている:

class InnerHolder(
    override val containerView: View?) : RecyclerView.ViewHolder(containerView), LayoutContainer { 
    fun bind(int: Int) { 
     textview.text = int.toString() 
    } 
} 

そして、これは完全にキャッシュされたを使用します。再生回数:

 TextView var10000 = (TextView)this._$_findCachedViewById(id.tv_text); 

しかし、問題は、キャッシュされたビューがLayoutContainerの範囲内にある必要があることです。例えば、この実施文句を言わない作業:

TextView var10000 = (TextView)$receiver.getContainerView().findViewById(id.tv_text); 

だから私の質問は、何らかの方法でキャッシュを維持する方法があり、まだアンドロイドを使用して:

class InnerHolder(
    override val containerView: View?) : RecyclerView.ViewHolder(containerView), LayoutContainer { 
    fun bind(int: Int) { 
     this.bindInt(int) 
    } 

} 
// some extension function outside the ViewHolder Scope. 
fun LayoutContainer.bindInt(int: Int) { 
    tv_text.text = int.toString() 

} 

これはまだビューを見つけるためにfindViewByIdを使用します。私のアダプターで拡張されていますが、ビュー所有者の範囲外ですか?

+0

ホルダークラス内のすべての 'View'参照を保持し、' init'ブロック内でのみ 'findViewById'を呼び出すことができます。 – Ircover

+0

あなたの質問を更新して、あいまいさを反映させてください。また、アダプタをインスタンス化するユースケースを追加します。たぶん私は後で答えを見つけるでしょう... – tynn

+0

@tynnはい。アップデートを確認してください。御時間ありがとうございます! –

答えて

1

あなたはこのように使用することができます:

innerHolder.apply { 
    tv_text.text = "test" 
} 

が、それはこのに逆コンパイルします:@linx

に触発さ

TextView var10000 = (TextView)innerHolder._$_findCachedViewById(id.tv_text); 
var10000.setText((CharSequence)"test"); 
0

を私はちょうどInnerHolderに拡張機能を作成する代わりにLayoutContainer場合。コンテキストは、Android Extensionにキャッシュされたビューを取得するのに十分な情報を与えます。

class InnerHolder(
    override val containerView: View?) : RecyclerView.ViewHolder(containerView), LayoutContainer { 
    fun bind(int: Int) { 
     this.bindInt(int) 
    } 

} 
// some extension function outside the ViewHolder Scope. 
fun InnerHolder.bindInt(int: Int) { 
    tv_text.text = int.toString() 

} 

これは私がしたい正確に何である

TextView var10000 = (TextView)$receiver._$_findCachedViewById(id.tv_text); 

にコンパイルされます。

関連する問題