Preparing a Wedding like an Android Developer — Part 2

Marcel Pintó
The Startup
Published in
4 min readNov 6, 2018

On the previous post, I introduced the tooling and some tips on how to organize the wedding preparation. In this part, we will focus on The App Architecture.

The features

We wanted something more than just a Yes/No app. First, we defined the main high-level functions to have in the application:

  • Personalized login
  • Invitation home screen
  • Invitation response
  • Information (location, agenda, how to get there, etc.)
  • Guestbook

The constraints

There were several constraints we needed to address.

  • The app will be used exclusively by our guest.
  • It should be easy to install and open.
  • It will be used by young and older generations.
  • I am from Barcelona, and my wife is from Germany. Thus we needed two languages. (Catalan and German)
  • Some information is not yet fixed so we should be able to change the content without requiring the people to update the app.

The Architecture

After the high-level features and the constraints were identified, I started designing the architecture draft.

  • 100% Kotlin
  • Use of new Android architecture components (ViewModel, LiveData, …)
  • Firebase Real-time Database
  • Firebase Authentication
  • Firebase Dynamic links

Be reactive

The main idea was to combine the architecture components with a reactive concept using Firebase.

The picture above shows the flow and interaction between different components. Let’s break it down.

  1. Fragments are passive, they observe the ViewModel Resource.
  2. The ViewModels observe, one or multiple Repository resources.
  3. The Repositories handle the creation and caching of Firebase LiveData Resources.
  4. The Firebase LiveData resource is an object that extends LiveData and adds or remove a listener to the given Firebase database reference.
  5. When Data changes, the change is forwarded to the observers
  6. The ViewModel will transform the resource, if needed, and deliver it to the fragment
  7. The Fragment will finally apply the given resource to the view.

The most crucial element in this setup is the FirebaseLiveData, let’s take a closer look:

It’s a simple class but with “superpowers”. Why I am saying that? Because this class underneath is handling the following:

  • Network layer.
  • Parsing entities.
  • Release resources when no observers attached.
  • Keep the state of the resource (Loading, Error, Completed).
  • Offline synchronization.
  • Reactive changes. When something change, locally or remotely, the observers get notified.

All that, thanks to the combination of LiveData and Firebase Realtime Database, making this setup “Reactive”.

Home Page

To showcase the above concept, we will take a look at the Home Page.

The HomeRepo provides a public method to get the HomePage resource LiveData. The HomePage is a simple data class with the needed fields to display the UI.

Internally in the repository we are using the UserRepo to get the language of the user and create our FirebaseLiveData, that will provide the HomePage resource based on the given language.

We built our data entities in a way that the view can use them directly to display the UI (not everywhere but in most of the screens). Thus in this case the ViewModel is just forwarding the Resource.

class HomeViewModel(repository: HomeRepo) : ViewModel() {

val homePage: LiveData<Resource<HomePage>> by lazy {
repository.getHomePage()
}
}

Finally, we only have to implement the view side. In this case the HomeFragment is the responsible to observe the ViewModel resource and update the view elements.

Showcase

In the gif below, we have, on the left side, the Firebase database console and on the right side, our app in the HomePage. Every time we change a value, it takes less than a second to be reflected in our app.

That allows us to modify any value of the full application in Runtime, no updates needed, no hardcoded values.

On top of that, we set the Firebase to work offline so once the user opened at least once the screen, it does not require network anymore to work.

val instance = FirebaseDatabase.getInstance().apply {
setPersistenceEnabled(true)
}

On the next post we will tackle the guests On-Boarding
Stay tuned!

This story is published in The Startup, Medium’s largest entrepreneurship publication followed by +385,976 people.

Subscribe to receive our top stories here.

--

--

Marcel Pintó
The Startup

Android and Flutter expert, founder of https://pibi.studio a mobile experts hub for building apps and providing expertise. Other projects: https://namewith.ai