formula icon indicating copy to clipboard operation
formula copied to clipboard

Passing side-effects to rendering layer.

Open Laimiux opened this issue 4 years ago • 2 comments

What

Currently, there isn't a well-defined mechanism for passing side-effects to the rendering layer.

Using SingleLiveEvent concept

class SideEffect<Type>(val value: Type) {
  private var performed: Boolean = false
  inline fun performIfNeeded(crossinline action: () -> Unit) {
    if (!performed) {
      performed = true
      action()
    }
  }
}


renderModel.scrollToTopSideEffect?.performIfNeeded {
  recyclerView.scrollToTop()
}

The limitation is that there cannot be multiple things trying to handle the same side-effect. The side-effect should always be handled by a single RenderModel consumer.

Using Relay concept

Side effect relay type passed through RenderModel

data class MyFeatureRenderModel(
    val scrollSideEffects: SideEffect<ScrollPosition>
)

Rendering layer

class MyFeatureRenderView(): RenderView<MyFeatureRenderModel> {
    private val recyclerView: RecyclerView = ...
    private val scrollEffectHandler = SideEffect.Handler { effect: ScrollPosition ->
        recyclerView.scrollTo(effect.position)    
   }

    override fun render = Renderer { model: MyFeatureRenderModel ->
        scrollEffectHandler.attach(model.scrollSideEffects)
    }   
}

Potential issues could be a missed side-effect event due to the subscription lifecycle. An effect could happen before the rendering layer is subscribed and can receive it.

Laimiux avatar May 14 '21 17:05 Laimiux

Perhaps you could emulate DispatchWorkSubject (source) and also take in a subscriber count (defaulting to 1) as requirement for emission?

I believe that would fulfill your requirements plus have the ability to queue multiple events while not subscribed.

Edit: I would like to add that DispatchWorkSubject emissions are exclusive to a particular observer. You would need to modify that implementation detail if you wanted a single event to be consumed by more than one observer.

jhowens89 avatar Aug 03 '21 18:08 jhowens89

Perhaps you could emulate DispatchWorkSubject (source) and also take in a subscriber count (defaulting to 1) as requirement for emission?

I believe that would fulfill your requirements plus have the ability to queue multiple events while not subscribed.

Edit: I would like to add that DispatchWorkSubject emissions are exclusive to a particular observer. You would need to modify that implementation detail if you wanted a single event to be consumed by more than one observer.

That seems like a good option that is worth exploring. Thanks!

Laimiux avatar Aug 03 '21 18:08 Laimiux