https://kotlinlang.org logo
#android
Title
# android
p

Paul Woitaschek

11/29/2018, 6:59 AM
It's a field of ViewHolder and you return that.
l

leosan

11/29/2018, 9:08 AM
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

Paul Woitaschek

11/29/2018, 10:10 AM
What is
BaseDelegateAdapter
?
l

leosan

11/29/2018, 10:17 AM
it's a basic recyclerView adapter implementation
p

Paul Woitaschek

11/29/2018, 10:18 AM
Then write an
ExtensionsViewHolder
which extends
ViewHolder
and implements
LayoutContainer
and return that subclass there.
l

leosan

11/29/2018, 10:18 AM
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

Paul Woitaschek

11/29/2018, 10:38 AM
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

leosan

11/29/2018, 10:41 AM
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

Paul Woitaschek

11/29/2018, 10:41 AM
What is "something like this"?
What's different?
l

leosan

11/29/2018, 10:42 AM
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

Paul Woitaschek

11/29/2018, 10:42 AM
That doesn't implement LayoutContainer
l

leosan

11/29/2018, 10:43 AM
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

Paul Woitaschek

11/29/2018, 10:43 AM
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

leosan

11/29/2018, 10:45 AM
I will do it then
p

Paul Woitaschek

11/29/2018, 10:47 AM
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

leosan

11/29/2018, 10:48 AM
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

leosan

11/29/2018, 12:53 PM
internally is the result different? because the bytecode is the same
just tested
p

Paul Woitaschek

11/29/2018, 12:54 PM
What did you test?
l

leosan

11/29/2018, 12:56 PM
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

Paul Woitaschek

11/29/2018, 12:56 PM
t should be
viewHolder.textView...
, not
<http://containerView.xyz|containerView.xyz>
.
VIEWHOLDER.textView
not viewHolder.CONTAINERVIEW.textView
l

leosan

11/29/2018, 12:57 PM
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

Paul Woitaschek

11/29/2018, 1:03 PM
Gimme a sec, I'll make a PR
l

leosan

11/29/2018, 1:04 PM
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

Paul Woitaschek

11/29/2018, 1:16 PM
Gradle is building for 15 minutes now 😄
l

leosan

11/29/2018, 1:17 PM
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

Paul Woitaschek

11/29/2018, 1:21 PM
Ehm
You didn't enable experimental extensions 😛
Copy code
androidExtensions {
  experimental = true
}
Read the readme of groupie
l

leosan

11/29/2018, 1:22 PM
I just commit with that change
p

Paul Woitaschek

11/29/2018, 1:23 PM
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

leosan

11/29/2018, 1:24 PM
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

leosan

11/29/2018, 1:29 PM
changed and stills
TextView var10000 = (TextView)itemView.findViewById(id.textView);
p

Paul Woitaschek

11/29/2018, 1:30 PM
Don't use itemView.textView but viewHolder.textView
l

leosan

11/29/2018, 1:37 PM
I'm not anymore 🤣
p

Paul Woitaschek

11/29/2018, 1:45 PM
I don't know what's wrong with groupie but for your own class it works like this:
l

leosan

11/29/2018, 1:48 PM
when you decompile can you show me a print of your bytecode please?
of the
DummyModel
specifically
2 Views