It's a field of ViewHolder and you return that.
# android
p
It's a field of ViewHolder and you return that.
l
I don't have the itemView at the creation of the Delegate, if you check the code it's created and passed on the bind method which is invoked by a viewholder class after its creation. So if I call itemView.myView the compiler will still produce a findViewById inside this Bind method where I want to use the cached version
p
What is
BaseDelegateAdapter
?
l
it's a basic recyclerView adapter implementation
p
Then write an
ExtensionsViewHolder
which extends
ViewHolder
and implements
LayoutContainer
and return that subclass there.
l
But instead of doing the binding logic there I register these delegated adapters and I delegate to then, something very similar to `groupie`/`epoxy` library do
Yeah I was thinking that after looking at the groupie implementaion https://github.com/lisawray/groupie/blob/master/example/src/main/java/com/xwray/groupie/example/item/CardItem.kt But one thing I didn't understand is see how the CardItem here extends
Item
which is basically what you said? I looked at the byte code and it stills this
Copy code
Intrinsics.checkParameterIsNotNull(viewHolder, "viewHolder");
      TextView var10000 = (TextView)((LayoutContainer)viewHolder).getContainerView().findViewById(id.tvHeadline);
I'm not sure if the calling
getContainerView().findViewById
is the same thing as calling
_$_findCachedViewById
even extending ViewHolder and making it implements
LayoutContainer
internally the kotlin synthetic doesn't know about the delegated class and don´t generate the
findCacheViewById
I could be wrong but it seems to me that it's the same thing as not using
LayoutContainer
p
Maybe you are using an outdated version?
I just tested:
Copy code
class ExtensionViewHolder(view: View) : RecyclerView.ViewHolder(view), LayoutContainer {
  override val containerView: View = itemView
}

fun bind(holder: ExtensionViewHolder) {
  holder.title.text = "hello"
}
And the bytecode for that is:
Copy code
LINENUMBER 13 L1
    ALOAD 0
    GETSTATIC com/yazio/android/coach/R$id.title : I
    INVOKEVIRTUAL com/yazio/android/coach/data/ExtensionViewHolder._$_findCachedViewById (I)Landroid/view/View;
    CHECKCAST android/widget/TextView
    DUP
    LDC "holder.title"
    INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkExpressionValueIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
    LDC "hello"
    CHECKCAST java/lang/CharSequence
    INVOKEVIRTUAL android/widget/TextView.setText (Ljava/lang/CharSequence;)V
   L2
l
yes if you do the way you did it works fine, but let's say you have something like this (groupie or my baseadapter)
p
What is "something like this"?
What's different?
l
typing sorry 😛
Copy code
inner class ViewHolder(
        parent: ViewGroup,
        @LayoutRes layoutRes: Int
    ) : RecyclerView.ViewHolder(parent.inflate(layoutRes)) {
       //This will delegate to another class
        fun bind(item: BaseViewType) = delegateAdapters[item.getViewType()]?.bindView(itemView, item, this)
    }

`
p
That doesn't implement LayoutContainer
l
even if I make this ViewHolder extends Layout container the other class that is actually making the binding similar to the one I sent you from groupie, doesn't know anything about LayoutContainer
p
the one I sent you from groupie, doesn't know anything about LayoutContainer
Yes it does
It takes a ViewHolder which implements LayoutContainer
Post a minimal self-contained example which demonstrates your issue please
l
I will do it then
p
And btw it only works explicitly
So the original line:
override fun bindView(itemView: View, item: BaseViewType, viewHolder: RecyclerView.ViewHolder) {
That
viewHolder: RecyclerView.ViewHolder
must be
viewHolder: ExtensionViewHolder
l
I'm gonna try it here on a self-contained project
Thanks for the attention https://gitlab.com/leobrujah/kotlin-synthetic-test/blob/master/app/src/main/java/com/test/kotlinsyntheticssample/MainActivity.kt here it is two adapters on a self-contained project, one using the library groupie and other one using my own basic implementation
both of them not using cache
Here you are not using LayoutContainer at all
Here you are not using the ViewHolder at all
It should be
viewHolder.textView...
, not
<http://containerView.xyz|containerView.xyz>
.
l
internally is the result different? because the bytecode is the same
just tested
p
What did you test?
l
either
viewHolder.textView
or
<http://containerView.xyz|containerView.xyz>
or
<http://itemView.xyz|itemView.xyz>
or
<http://viewHolder.containerView.xyz|viewHolder.containerView.xyz>
produces the same exactly bythe code which is
findViewById
p
t should be
viewHolder.textView...
, not
<http://containerView.xyz|containerView.xyz>
.
VIEWHOLDER.textView
not viewHolder.CONTAINERVIEW.textView
l
have you read what I said? 😄
I don't think you understand the fact the viewHolder is being passed trought the
bind
method so the container class doesn't have a clue about
LayoutContainer
this way kotlin compiler can't generate
findViewByCache
if you run the project and decompile by yourself I think you can see what I´m saying
implementing LayoutContainer by itself doesn´t do any caching magic ... it´s just so the compiler can generate the cache bytecode to it´s containing class and since the delegates RECEIVE an instance of the VIEWHOLDER it doesn´t matter how the heck I call it, the compiler can't generate the cached code
p
Gimme a sec, I'll make a PR
l
thanks for the patience 😛
@Paul Woitaschek I've just updated with the change I mention calling
viewHolder.textView
as you mention, just so you can see that I tried
p
Gradle is building for 15 minutes now 😄
l
so the code looks like this
Copy code
override fun bind(viewHolder: ViewHolder, position: Int) {
        viewHolder.textView.text = content
    }
and the generated bytecode
Copy code
TextView var10000 = (TextView)((LayoutContainer)viewHolder).getContainerView().findViewById(id.textView);
p
Ehm
You didn't enable experimental extensions 😛
Copy code
androidExtensions {
  experimental = true
}
Read the readme of groupie
l
I just commit with that change
p
Copy code
// IMPORTANT!  Enables view caching in viewholders.
   // See: <https://github.com/Kotlin/KEEP/blob/master/proposals/android-extensions-entity-caching.md>
    androidExtensions {
        experimental = true
    }
l
I also commited now at the bottom a version where the cache does work (but does not suits my purposes)
Copy code
class CachedViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView), LayoutContainer {
    fun bind(model: DummyModel) {
        textView.text = model.content
    }
}
so you can decompile and see the difference between my implementation / groupie / and the normal one with the bind directly on the viewHolder and not delegated
This line
should have
ExtensionsViewHolder
as it's signature
l
changed and stills
TextView var10000 = (TextView)itemView.findViewById(id.textView);
p
Don't use itemView.textView but viewHolder.textView
l
I'm not anymore 🤣
p
I don't know what's wrong with groupie but for your own class it works like this:
l
when you decompile can you show me a print of your bytecode please?
of the
DummyModel
specifically