Trying to impact RecyclerView items via EventBus

狂风中的少年 提交于 2021-01-27 17:18:25

问题


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)
}
...

回答1:


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()
}



回答2:


I worked with EventBus very little, prefer RxBus:

object RxBus {

    private val bus = PublishSubject.create<Any>()

    fun send(event: Any) {
        bus.onNext(event)
    }

    fun <T> observeEvent(type: Class<T>): Observable<T> =
        bus.ofType(type)
}

class NeedToUpdateEvent

For sending event:

RxBus.send(NeedToUpdateEvent())

For subscribing to event:

RxBus.observeEvent(NeedToUpdateEvent::class.java)
        .subscribe { / some action / }

You can try this



来源:https://stackoverflow.com/questions/51378699/trying-to-impact-recyclerview-items-via-eventbus

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!