Search code examples
androidkotlingreenrobot-eventbus

Trying to impact RecyclerView items via EventBus


I'm trying to post an EventBus event from an recycler item view class and subscribe to it in the same class so that the event is grabbed by ALL the recycler items.

Now in more detail:

I have a RecyclerView where each item (FriendListItem.kt) has a context menu. Only one context menu should be shown at a time. That means that I need to close another item's context menu if its visible.

I chose to use the org.greenrobot.eventbuswhich we already widely used in our app. In the item class, when the menu is to be shown, I post an event, and the grab it in the same class. I thought that this way all the items will respond and dismiss their (possibly visible) menus, but the event Subscriber doesn't grab anything.

I'll just add that the containing fragment registers and unregisters the EventBus as it should because it works fine in another event.

The problem here might be that the event should be grabbed in a recycler item view, which manifests in multiple items. Could that be it?

Here is the item:

package com.myapp.android.common.social.friends

import android.content.Context
import android.text.Spanned
import android.view.View
import android.view.View.OnClickListener
import android.widget.ImageView
import android.widget.LinearLayout
import com.myapp.android.common.R
import com.myapp.android.common.database.room.entities.User
import com.myapp.android.common.generic.coachmark.BubbleCoachMark
import com.myapp.android.common.image.ImageSize
import com.myapp.android.common.social.friends.events.FriendsListResetOtherMenus
import kotlinx.android.synthetic.main.friends_list_item.view.*
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode

class FriendsListItem(context: Context) : LinearLayout(context) {

    private var user: User? = null
    private var menu: BubbleCoachMark? = null

    init {
        View.inflate(context, R.layout.friends_list_item, this)
    }

    fun updateView(user: User, sp: Spanned?) {
        this.user = user

        // Avatar
        if (user.pictureUrl != "") {
            setUserPicture(user.pictureUrl + "", user.isPremium)
        }

        // Premium
        when {
            user.isPremium -> friendPremium.visibility = View.VISIBLE
            else -> friendPremium.visibility = View.GONE
        }

        // Name
        when (sp) {
            null -> friendName!!.text = user.name
            else -> friendName!!.text = sp
        }

        // Friend Status
        invite.visibility = View.GONE
        action.visibility = View.VISIBLE

        when (user.status) {
            User.Status.friend -> {
                action.setImageResource(R.drawable.ic_friend_options)
                action.setOnClickListener(OnClickListener {
                    EventBus.getDefault().post(FriendsListResetOtherMenus())
                    when (menu) {
                        null -> {
                            menu = BubbleCoachMark(BubbleCoachMark.BubbleCoachMarkBuilder(context, action, FriendsListItemMenu(context)).setShowBelowAnchor(true))
                            menu!!.show()
                        }
                        else -> {
                            if (!menu!!.isShowing)
                                menu!!.show()
                        }
                    }
                })
            }
            User.Status.pending -> {
                action.setImageResource(R.drawable.ic_friend_requested)
            }
            User.Status.nofriend -> {
                action.setImageResource(R.drawable.ic_friend_add)
            }
            else -> {
                invite.visibility = View.VISIBLE
                action.visibility = View.GONE
            }
        }
    }

    fun setUserPicture(pictureUrl: String, isPremium: Boolean) {
        synchronized(this) {
            friendAvatar!!.scaleType = ImageView.ScaleType.CENTER_CROP
            friendAvatar!!.setUserPicture(pictureUrl, isPremium, R.drawable.profile_silhuette_new, ImageSize.thumbnail)
        }
    }

    // The method here is not grabbing the event
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEventMainThread(event: FriendsListResetOtherMenus) {
        if (menu != null && !menu!!.isShowing)
            menu!!.dismiss()
    }
}

Updated solution:

Registered the EventBus locally in the init clause:

...
init {
    View.inflate(context, R.layout.friends_list_item, this)

    EventBus.getDefault().register(this@FriendsListItem)
}
...

Unregistered the EventBus in the onDetachedFromWindow event:

...
override fun onDetachedFromWindow() {
    super.onDetachedFromWindow()

    EventBus.getDefault().unregister(this@FriendsListItem)
}
...

Solution

  • Try this. It happened with me for kotlin Int, it might resolve your issue

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEventMainThread(event: FriendsListResetOtherMenus?) {
        if (menu != null && !menu!!.isShowing)
            menu!!.dismiss()
    }