我可以推迟使用Kotlin Android扩展适配器的视图绑定

Kotlin Android扩展提供了一种直接在Activity / fragment / Adapters中使用ID的方法。 所以我想要的是适配器的通用方式,并将绑定视图职责留给适配器的用户,而不是适配器本身。 例如 :

class GenericAdapter( @LayoutRes private val layoutId: Int, private var list: List, inline private val bind: (View, T, Int) -> Unit) : RecyclerView.Adapter() { 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(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)); 

但是他们有一个带有Android扩展的实验工具,例如一个LayoutContainer

 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的范围内。 例如,这个实现不会工作:

 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来查找视图:

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

所以我的问题是有办法以某种方式保持缓存,仍然使用Android扩展与我的适配器,但超出了视图的范围?

你可以这样使用:

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

它会反编译成这个:

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

灵感来自@linx

如果我只是创建一个扩展函数InnerHolder而不是LayoutContainer 。 上下文给Android扩展提供足够的信息来获取缓存视图。

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

这正是我想要的。