- Notifications
You must be signed in to change notification settings - Fork21
Reactive Virtual DOM for Android.
License
lyft/domic
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Domic is an abstraction for Android UI layer that mirrors real AndroidDOM, butreactively.
It allows you:
- Unify interactions with Android UI layer across codebase
- Unit test UI-related code with in-memory implementation of Virtual DOM
- Efficiently render complex state objects (MVI/Redux)
- Enforce async-only interaction with UI layer across codebase
- Reuse existing Android DOM: Views, Widgets, Layouts
Domic —DOMe like.
- Motivation
- State of the Project
- Examples
- Key Take-Aways
- Implementation Details
- Integrating with Existing Projects
- Alternatives
- Terminology
- Credits
Scaling Android app codebase and development is complicated. Part of that complication comes from constant need in interaction between app's business logic and UI.
In recent years, lots of progress has been made by community in adopting, inventing and redesigning patterns that other platforms use to solve similar problems: MVP, MVVM, MVI, Redux, etc.
With help of reactive libraries likeRxJava combining streams of data and expressing complicated logic became easier.
It naturally shifted application code into a form of reactive cycle where app state is combined with user input and new state is produced for rendering. It was always a cycle, but it's more explicit now.
However we've found that existing approaches have problems with scaling for such reactive rendering cycles and we think there is something that can enhance them to fix those problems.
We think that Domic, aReactive Virtual DOM, can be that enhancement layer.
It is important to say that there are existing projects that overlap with Domic's functionality but with different trade-offs. Please refer toAlternatives section for details.
At the moment Domic is an experimental project.
It means that Lyft is not using it in productionyet. We do however think that this is a perspective direction that will help to shape, scale and move Android and client-side development further in general.
The project doesn't have a public release yet becausewe want to gather some feedback from community to make sure we didn't make major design errors as scope and internal complexity of the project are quite high.
We're planning to start shipping0.1.0
version soon though, pleasestay tuned!
Right now we expect community members interested in this project to clone it and play with its source code andsamples
, submit issues and pull requests to shape the project!
val nameOfDocumentObject:VirtualType=BindingType()
val search:EditText=AndroidEditText(v.findViewById(R.id.search))
search.observe.textChanges:Observable
search .observe .textChanges .debounce(300,MILLISECONDS, timeScheduler) .switchMap { searchService.search(it) }
search.change.enabled(Observable):Disposable
searchState .map {when (it) {isInProgress->falseisFinished->true } } .startWith(true) .subscribe(search.change::enabled)// `(Observable) -> Disposable` is an extension function Domic provides.
val nameOfDocumentObject:VirtualType=BindingType()
val search:EditText=TestEditText()
search.simulate.text("search term")
assertThat(search.check.enabled).isEqualTo(false)
Domic doesnot require you to rewrite layouts or adopt a new framework to build UI.
Domic binds to existing Android Framework DOM (UI components: Views, Widgets) so you can continue to use all the tooling and libraries you're used to: Views, Widgets, Layouts, Support Library, Layout Preview, IDE, build system.
Domic takes care of threading.
You can observe state on non-main thread(s), you can change state from non-main thread(s).
This allows to minimize workload on main thread thus giving it more time for rendering and handling user input.
Tip:
You can run
Presenter
/ViewModel
/Model
/Reductor
on non-main thread(s) and only use main thread for minimal amount of required interactions with real AndroidDOM.
Domic takes care of computing diff between previous state and new one thus only rendering what is different.
Motivation: Android Framework already diffssome state changes, typically, simple ones, likeTextView.setEnabled()
. However there are relatively expensive state changes likeTextView.setText()
that are not diffed by Android Framework and can require re-rendering, computations, notifying listener(s) and so on.
Tip:
You can drop complex state objects on Domic (like Redux or MVI are designed to work) and let it figure what needs to be rendered.
Domic makes sure you can observe state of same property with multipleObserver
s.
Typical example would be observing clicks on AndroidView
: AndroidView
can only have one click listener at a time, subsequentObserver
effectively detaches previous one from theView
.
Domic howevershare()
s theObservable
allowing multipleObserver
s observe same state.
Domic is an abstraction.
Bindings to real AndroidDOM is just one implementation of that abstraction.
Domic has separate in-memory implementation of the Virtual DOM that let's you unit test yourPresenter
/ViewModel
/Model
/Reductor
.
Domic provides synchronous testing API to easesimulating andchecking state changes.
Tip:
You can take Domic further andrendered whole app in memory thus be able to run functional and integration tests in memory on JVM*!*
Domic is type safe.
Observing state and changing state encapsulated intoseparate types withing each Document Object. ieButton.Observe
andButton.Change
.
This allows one to haveread-only orwrite-only reference to a Document Object, thus pushing type safety even further.
Tip:
You can take Domic further and maybe even create a new MV-design with clear separation of code that
Observe
s andChange
s UI?
TODO
DOM stands forDocument Object Model. Term itself comes from early days of web development (1998), however it's abstract enough and pretty much reflects how Android UI system works: Layouts, Views, Widgets, XML-based markdown language, memory model.
Domic however as of now doesn't track child-parent relationship between Document Objects, instead Domic binds to real DOM objects thus leaving layouting to the real DOM.
Since Domic is a Reactive Virtual DOM for Android, we use Document Object as a name for Widget/View/Component type or instance.
It is however valid to call them Widget, View or Component, but Document Object is preferred, specifically for reasons of possible multiplatform support and for sake of easier discussions with developers working on other platforms.
Diffing is a process of computing difference between previous known state and new state. Every property that Domic allows to change for a given Document Object is going through comparison with its previous state, thus eliminating updates of real DOM if they're not required.
Rendering is a process of reflecting in-memory state of Virtual DOM on the real DOM.
As many other things in the tech world: programming languages, libraries, cluster management systems, build tools, etc, Domic isnot an invention, but rather a compilation of ideas and experience.
Domic was influenced by:
Special credit ❤️ goes toJuno Android team, specifically Igor Korotenko for development efforts in similar direction.