Tuesday, January 28, 2020

One state, two state, previous state, new state

With the latest changes to PYDroid in 28, you'll probably notice that when renders occur, the render function is called only with a single State parameter. In fact, throughout the history of the PYDroid Arch library, there has never been an instance where the previous state was also passed through the render. PYDroid doesn't pass the previous state, PYDroid doesn't like the previous state.

Why not?

Ultimately, its a philosophical decision and not a technical one. Before we dive deeper, we should understand why the previousState is generally a wanted thing.

In many cases with MVI frameworks, the render function is responsible for drawing and updating the entire visual part of state. In many cases, the previousState and current state are used in this render function to avoid unneeded renders or re-renders. Sounds like a good thing, so why doesn't PYDroid like it?

I would argue that the point of MVI is to simply how to draw a screen - by giving the consumer a single parameter and saying "everything on screen must come from this state object". By including in the mix a previousState, the idea of rendering on to the screen is now a function where the output is a complex combination of two very specific inputs, instead of just a simple object. Adding previousState makes it just as tedious to track proper state as one would experience in a non MVI setup. It does have the nice benefit of avoiding un-needed drawing and rendering, but at what cost?

So then PYDroid doesn't use previousState, so therefore PYDroid can cause useless rerendering and is slow. Well - not quite. PYDroid debounces on states which are the same - if a state change ultimately results in the exact same state as the one before it, the render is never called. This is different from a framework like React, which will render each time setState is called as long as shouldComponentUpdate is true.

Then, how does PYDroid avoid the situation where a state change occurs, but only one component of the state has actually changed? For example, if your state holds an error Throwable and a loading boolean - how can you avoid re-rendering the view when only one of these changes but not the other? Well, PYDroid does nothing. It just sends the render call to the view layer.

But remember what our View layer is. We are not on the web, where the View is created and rendered as just a DOM - we are on Android. Android views largely handle these duplicate state issues on their own. Passing the same text string to a TextView will not cause a redraw. Passing a drawable to an ImageView will not reload it. Passing a new list to a RecyclerView adapter will be diffed via the submitList function, and only the individually changed ViewHolders will be re-rendered. Basically, PYDroid doesn't care - it delegates the responsibility of avoiding useless rendering to the View layer which does the rendering. In the event that you really need to manage previous states and avoid re-rendering, you can keep track of the specific components of state on your own.

Maybe in the future this may change if decide it is more trouble to not have previousState - but at least for the lifespan of 28, PYDroid will be a single state MVI framework.

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================