Evolution of the Helium Framework — Part 1 — A new way to build Android Apps
For a while now, I’ve been working on Helium in my spare time. I built Helium to make Android development feel easy, fast, and fun, whether you’re building a quick prototype or a professional app.
I’ve completely changed the API in this latest iteration (v0.5.0) and wanted to share the story behind it. It breaks conventions, introduces a new mental framework and a fresh approach for building Android apps.
The big breakthrough happened while trying to re-name some of the core classes of the framework. Naming is hard. Good API design is a lot about choosing what vocabulary your users will have to learn to talk to you. Naming things is a big decision, because everything else derives from that.
Finding appropriate names for these core classes forced me to step back and think about the concept of the framework itself.
Helium is built for simplicity and ease of use, it’s a framework that encourages you to build your app as a collection of self contained, re-usable components. I wanted the API to reflect that.
One analogy that kept coming to mind is that building apps should feel like assembling Lego™ blocks. I used to love building things with Lego™ when I was a kid, so I started to think about it it terms of software. While visualizing this idea and looking at my code, suddenly, all the pieces fell in place (pun intended).
Helium proposes the following mental model to structure your code:
UiBlock
— a class that handles rendering the UILogicBlock
— a class that handles logic, in other words, the block’s behaviorAppBlock = (LogicBlock + UiBlock)
— assembling Logic with UI creates a fully functional component of your app.
An App is just a bunch of App Blocks assembled together! I like how natural it is to visualize this concept, because it has a representation in the physical world.
Just like Lego™ blocks, or puzzle pieces, a UIBlock
can only be assembled with a LogicBlock
if they are compatible — if they “fit” together.
In code, this is handled by two interfaces representing the “connectors” between blocks: BlockState
and BlockEvent
.
- A
LogicBlock
exposes aBlockState
and expects (handles) aBlockEvent
- A
UIBlock
exposes aBlockEvent
and expects (renders) aBlockState
Logic and UI have no reference to each other, they’re completely self contained, which makes individual blocks highly reusable. It’s also easy to swap a UiBlock
for another while keeping the same logic or vice versa, as long as the blocks “fit” together.
Logic blocks can be composed of smaller logic blocks. UI blocks can also be composed of smaller UI blocks. App blocks link logic and UI together, and can define child App blocks which get recursively linked.
This makes building App blocks infinitely scalable, you can create App blocks composed of multiple App blocks which themselves are composed of multiple App blocks and so on.
Leveraging the power of Kotlin, using a mix of extension functions and operator overloads, this is what the API looks like to assemble blocks in an Activity
or Fragment
:
val logic = MyLogic()
val ui = MyUi(layoutInflater)
assemble(logic + ui)
That’s it. Dead simple. No explanation needed.
From there, you can build up your logic independently from your UI, keeping your code neatly organized and maintaining separation of concerns.
To see more code examples, and more detailed information on the implementation, head over to GitHub.
On the next part of this series, I’ll write about some of the pre-built, highly re-usable App Blocks that Helium provides, which save so much time and effort.
Everything is already available on GitHub:
And more to come!
I’ve been really enjoying using this framework for my projects, curious to hear if it resonates with other people. Feedback and contributions are welcome!