I was wondering if the way how Litho works right now could be slightly changed so that components could be instantiated without any Android dependencies (i.e. no context etc).
Something like
Row.create() // no context
.child (
Text.create() // no context
.text("Hello")
.build())
.child(
Text.create() // no context
.text("World")
.build())
.build()
So components would be just POJOs describing how the UI should look like. Then LithoView could render this POJOs to real UI widgets (using android dependencies like context etc.)
I think this would be a major improvement regarding testing. Imagine you have a Presenter in MVP (or whatever architectural pattern you prefer) that loads some data from business logic. The Presenter would “map” the data from business logic to LithoComponents and then call view.render(lithoComponentPojos) which then would use LithoView to actually render that components. If we could write litho components without android dependencies, we could easily test this architecture on the jvm with simple unit tests like
Row expected = Row.create().child(...).child(...).build();
assertEquals(expected, rowGeneratedByPresenterAndHandOverToView);
I’m sure this is not a simple change and not sure if this is technically possible with the current architecture of Litho, but is it something you would consider while moving towards 1.0?
I've actually been thinking about this too. My thought so far was to have a MockContext that would alleviate the need for Robolectric or a full instrumentation test, but having a way to leave out the contexts altogether would be even better.
I'm not sure if that would work once we'd want to test anything related to state because I think there's some stuff happening in ComponentContext to enable that.
I'm not 100% sure, but after taking a quick look at the source code of a generated Component it seems that context is mostly used to access android resources. I think this could be done lazily so that no context is needed at all in the component POJO. Wouldn't it be possible to do that lazily when LithoView starts to build the actual UI widgets? To me (without any deep knowledge of Litho internals) it seems having a context in LithoView and the components LayoutSpec should be enough, isn't it?
Hey @sockeqwe, right now the component context is also holding on to information that is needed to perform state updates. Check out these lines: https://github.com/facebook/litho/blob/master/litho-core/src/main/java/com/facebook/litho/ComponentContext.java#L103#L127. We thought about holding onto that information in a separate object, but that would have introduced a new concept in the API and we tried to keep it simple.
Thanks @mihaelao! I think the closest we can get to this to enable easier testing is by having a MockComponentContext or similar which can be initialized without access to a real underlying Android Context. We could probably keep the state update logic around in there.
Having something like "stateless" Components similar to how they exist in React may also be something fun to think about for a model like @sockeqwe proposes it.
Closing, ComponentContext is not extending from Android context anymore. There are also plans to make the ComponentContext lighter and extract all the info that the framework needs, such as state update data, to another class which would not be accessible on the developer side
Most helpful comment
Hey @sockeqwe, right now the component context is also holding on to information that is needed to perform state updates. Check out these lines: https://github.com/facebook/litho/blob/master/litho-core/src/main/java/com/facebook/litho/ComponentContext.java#L103#L127. We thought about holding onto that information in a separate object, but that would have introduced a new concept in the API and we tried to keep it simple.