0

I have a ViewHolder than contains, among other widgets, a SeekBar. The SeekBar has a Listener, which is added during the onCreateViewHolder call.

Since the onBindViewHolder method is used to configure the Views held by the ViewHolder, how can that Listener then act upon the new dataset represented by the ViewHolder's Views?

Is it OK to add a member variable of type Object to the ViewHolder, which contains a reference to the dataset, so that the Listener can then take this object and modify a variable in the dataset during SeekBar-changes? Or is this an Anti-Pattern?

The dataset object referenced by that member variable would then get swapped out on every onBindViewHolder in order to "point" to the currently represented dataset.

Daniel F
  • 13,684
  • 11
  • 87
  • 116
  • you should set the listener to SeekBar in getView() method like viewHolder.seekBar.setOnSeekListener(your listener); – Stan Apr 07 '15 at 19:57
  • @Stan I'm using a RecyclerView.ViewHolder which apparently replaced `getView()` by `onCreateViewHolder()`. I'm already setting up the Listener in this method. The point is that the dataset which the displayed slider is acting upon changes as the views get recycled. I'm asking about which method is appropiate in order to have the ViewHolder know which dataset is currently associated to the Listener. – Daniel F Apr 07 '15 at 20:25

1 Answers1

1

If u r using a RecyclerView.ViewHolder then u do understand that usual ViewHolder pattern's getView() method is replaced here by 2 methods: onCreateViewHolder() and onBindViewHolder(). Method onCreateViewHolder() stands for creating VH or getting it from tag and onBindViewHolder() stands for filling VH's views with corresponding data. Understanding this the only place you shoud set the listener is onBindViewHolder() method.
If your question is about creating a Listener every time the onBindViewHolder() fires - its not a good idea. You better create one instance of a listener as (adapter) class field and use it. Usually I'm setting something to a target View's tag and this "something" is an object I need inside a listener.

private final View.OnClickListener onCancelClick = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        final SwipeLayout swipeLayout = (SwipeLayout) v.getParent().getParent();
        swipeLayout.close();
    }
};

and iside of a getView() or onBindViewHolder():

viewHolder.btnSwipeMenuCancel.setTag(swipeLayout);
viewHolder.btnSwipeMenuCancel.setOnClickListener(onCancelClick);

using a tag:

viewHolder.btnSwipeMenuReply.setTag(message);
viewHolder.btnSwipeMenuReply.setOnClickListener(onReplyToAuthorClick);

private final View.OnClickListener onReplyToAuthorClick = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        final Message message = (Message) v.getTag();
        activity.replyToMessageAuthor(message);
    }
};
Stan
  • 6,511
  • 8
  • 55
  • 87
  • Yes I thought about this, but it didn't seem right to set a new listener on every `onBindViewHolder()` call as the older ones would need to get GC'd afterwards. I'm currently setting it in the `onCreateViewHolder()`, and I've added an Object member variable to the ViewHolder which contains a reference to the corresponding which changes between every `onBindViewHolder()`, together with the view's "looks". My question is if it is OK to use such a variable in a ViewHolder, or if one shouldn't use that approach. (cont) – Daniel F Apr 08 '15 at 10:35
  • It works, but I don't know If it is more of a kludge rather than the appropiate solution. On the other hand, there should be a solution which groups the listener with the corresponding data, where the listener get's swapped out in the `onBindViewHolder()` so that it doesn't get GC'd when not in use. Then the listener would need to have a reference to the data it is acting upon, kind of like a closure. So `new Listener` would only get called once per dataset. – Daniel F Apr 08 '15 at 10:38
  • just create one instance of a listener (as a class field, with `final` modifier maybe) and set it every time. – Stan Apr 08 '15 at 10:40
  • Oh, so you mean that even multiple views of the same type should share the same listener? And the reference to the data the listener should be acting upon should be stored where? – Daniel F Apr 08 '15 at 10:52
  • So I should store the reference in the tag of the widget in question? Sounds interesting, will think about this. – Daniel F Apr 08 '15 at 10:54
  • These wigdets dies very fast right after going off the screen and also you are not creating a new object this way. The message object shown in my example is stored in a collection anyway. – Stan Apr 08 '15 at 10:56