Can I Defer The View Binding In An Adapter Using Kotlin Android Extension
Kotlin Android Extensions provide a way that using the IDs directly in Activity/fragment/Adapters. So What I want is a generic way for an adapter and leave the bind view responsibility to the user of adapter instead of adapter itself. For example :
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)
}
which I can just pass the layout file and bind function to bind the adapter as I want without rewriting the same code for every single layout file with and adapter.
But here is the problem: ViewHolder pattern want to eliminate call "findViewById" every time an ChildView inflated. But with my implementation of adapter. It needs to call "findViewById" every time when adapter bind a view.
Edit: for the details of the "cache" problem.
Using the GenericAdapter
in Activity. Like
override fun onCreated(savedInstanceState: Bundle?){
list.adapter = GenericAdapter<Item>(items){ view,item,position ->
view.textview.text = item.text
}
}
this will decompiled into this:
TextView var2 = (TextView)var10000.findViewById(id.textview);
Intrinsics.checkExpressionValueIsNotNull(var2, "itemView.tv_text");
var2.setText((CharSequence)String.valueOf(var1));
But they have a experimental tool with Android Extension with a LayoutContainer
for example :
class InnerHolder(
override val containerView: View?) : RecyclerView.ViewHolder(containerView), LayoutContainer {
fun bind(int: Int) {
textview.text = int.toString()
}
}
And this will perfectly use the cached views:
TextView var10000 = (TextView)this._$_findCachedViewById(id.tv_text);
But the problem is that the cached views need inside the scope of LayoutContainer. For example this implementation wont work:
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()
}
this will still use the findViewById to find the view:
TextView var10000 = (TextView)$receiver.getContainerView().findViewById(id.tv_text);
So my question is there a way to remain the cache in some way and still using Android Extension with my adapter but outside the scope of viewholder?
Answer
You can use like this:
innerHolder.apply {
tv_text.text = "test"
}
it will decompiled into this:
TextView var10000 = (TextView)innerHolder._$_findCachedViewById(id.tv_text);
var10000.setText((CharSequence)"test");
Related Questions
- → should I choose reactjs+f7 or f7+vue.js?
- → Phonegap Android write to sd card
- → Local reference jquery script in nanohttpd (Android)
- → Click to navigate on mobile devices
- → How to allow api access to android or ios app only(laravel)?
- → Access the Camera and CameraRoll on Android using React Native?
- → React native change listening port
- → What is the default unit of style in React Native?
- → Google play market autocomplete icon
- → Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of `ListView`
- → Using Laravel with Genymotion
- → react native using like web-based ajax function
- → react native pdf View