如何在环氧模型中处理订阅

时间:2018-06-20 09:31:04

标签: android android-recyclerview rx-java2

当前,我正在处理一个复杂的 recyclerview 布局,其中包含几种不同的模型类型。 为了构建基本结构,我使用了 Airbnb的Epoxy 库。 到目前为止,一切都很好。棘手的部分始于我希望每个单元具有一个单独的ViewModel (来自Android体系结构组件)的那一刻。 每个ViewModel中都有几个可观察对象。

一个非常基本的ViewModel示例:

class ExampleEntryViewModel @Inject constructor(private val exampleRepository: ExampleRepository) : ViewModel() {

    private val viewClickedSubject: PublishSubject<String> = PublishSubject.create()

    /**
     * Inputs
     */
    fun viewClicked() {
        viewClickedSubject.onNext("example string")
    }

    /**
     * Outputs
     */
    fun getPriceValue(): Observable<Float> = exampleRepository.getTicker() // this one pushes data in random intervals
            .map { it.price }

    fun handleClick(): Observable<String> = viewClickedSubject

}

这里是基本的环氧模型:

@EpoxyModelClass(layout = R.layout.item_example)
abstract class ExampleEntryModel : EpoxyModelWithHolder<ExampleEntryModel.ExampleEntryModelViewModel>() {

    @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
    var onEntryClickListener: EntryClickListener? = null

    @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
    lateinit var viewModel: ExampleEntryViewModel

    override fun bind(holder: ExampleEntryModelViewModel) {
        holder.apply {
            disposables.clear()

            disposables += viewModel.output.getPriceValue()
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe { currentPriceView.text = it }

            disposables += viewModel.output.handleClick()
                    .subscribe { onEntryClickListener?.onEntryClick(clickAction = it) }

            rootView.setOnClickListener { viewModel.input.entryClicked() }

        }

    }

    override fun onViewDetachedFromWindow(holder: ExampleEntryModelViewModel) {
        holder.disposables.clear()
        super.onViewDetachedFromWindow(holder)
    }

    override fun unbind(holder: ExampleEntryModelViewModel) {
        holder.apply {
            disposables.clear()
            rootView.setOnClickListener(null)
        }
        super.unbind(holder)
    }

    interface EntryClickListener {
        fun onEntryClick(clickAction: String)
    }

    class ExampleEntryModelViewModel : EpoxyHolder() {
        lateinit var rootView: ConstraintLayout
        lateinit var currentPriceView: TextView
        val disposables = CompositeDisposable()

        override fun bindView(itemView: View) {
            rootView = itemView.wrapperMain
            currentPriceView = itemView.currentPrice
        }
    }
}

问题是,有时我的订阅未被订阅或被多次订阅。 达到此目的的最佳方法是在列表中包含多个项(然后可以在一个屏幕上放置更多项),然后快速滚动到列表的底部和顶部。 结果是,某些条目会多次调用handleClick,而其他条目根本不会调用它们。 我认为问题在于某些订阅不会被处置,而另一些则无法被订阅(或在新订阅后被处置)。

有人知道如何解决吗?如何以正确的方式订阅和处置可观察物?

谢谢。

0 个答案:

没有答案