Building an Modern Android Application — Start Phase -I

Fabián Mondragón
4 min readDec 11, 2024

--

In today’s fast-paced tech world, finding a structured and personalized learning path can be challenging, especially for those new to the field. This article introduces the foundation of a project I’m building: an application for automatic roadmap generation. The goal is to help learners, at any stage, navigate their journey from beginner to expert in a specific technology.

In this article, I’ll walk you through the architecture and implementation of the “Start Phase -1” of the application, focusing on mobile Android development. You’ll learn about the clean architecture principles applied, the role of each layer, and how the UI and domain layers interact seamlessly to provide a great user experience.

Whether you’re a developer curious about building similar applications or someone interested in structured learning paths, this article has something valuable for you. Let’s dive in!

Tech Stack

  • Jectpak-compose
  • Coroutines
  • Flows
  • Clean Architecture (One module)
  • Git Actions
  • Hilt
  • Firebase Authentication
  • API ChatGpt

Building the Start Phase — I

The Start Phase is composed of a single ViewModel and a single screen in the UiLayer. In the Domain Layer, we include two core components: a UseCase and a Repository pattern. At this state, the repository only defines its interface.

In the sections below, I’ll explain in more detail what happens in each layer

UiLayer

When working thiw Clean Architecture, the UI layer is strcitly concerned with user interface-related tasks. For this reason, the ViewModel contains logic only for the following aspects:

  • Field Validation: it validates the email format and password format. If there’s an error during validation the ViewModel updates a corresponding StateFlow inmediately to inform the UI -> Observer Pattern

On the other hand, the screen observers the sate of these field managed by the ViewModel. Whenever there’s a change, the UI immediately displays a message to the user about the issue.

viewModelScope.launch {
_navigationEvent.value = ResultUi.Proccesing
val result = authenticationUseCase.registerUser(email= _email.value, password = _password.value)
when (result){
is RoadMapResult.Fail -> {
_navigationEvent.value = ResultUi.Fail (result.msg)
}
is RoadMapResult.Processing -> {
_navigationEvent.value = ResultUi.Proccesing
}
is RoadMapResult.Success -> {
Log.i("Navigation", "Success")
_navigationEvent.value = ResultUi.Success
}
}
}

Key Highlights

  1. Using lauchn in ViewModelScope: Launching coroutines with ViewModelScope ensure they are tied to the lifecycle of the ViewModel. this prevents memory leask by automatically canceling the coroutine when the ViewModel is cleared.
  2. _navigationEvent: this variable notifies the view of the user signup result on firebase. Whenever a result occurs (success, failure, or processing), the UI is informed and reacts accordingly

That’s all for the ViewModel logic for now.

Composable Function: Navigation Handling

@Composable
fun OnNavigationEvent(navigation: ResultUi, navController: NavHostController) {

when (navigation) {
is ResultUi.Fail -> LoaderExample(isLoading = false)
ResultUi.InitialState -> LoaderExample(isLoading = false)
ResultUi.Proccesing -> LoaderExample(isLoading = true)
ResultUi.Success -> {

LoaderExample(isLoading = false)
LaunchedEffect(navigation) {
navController.navigate(RoadMapRoute.hello.toString())
}

}

}
}

Explanation

In this function, the UI reacts to any changes in the navigation variable, which is updated by the ViewModel. Key behavior include:

  • The LoaderExample composable toggles visibilyt bases on the navigation state
  • When navigation is successful, a LaunchedEffect ensure that the NavController executes the navigation action only one per state change.

Backend Integration

In other parts of the code, the actual API call to Firebase is implemented. For this phase, the focus remains on structuring the clean architecture and handling UI logic efficiently.

Concepts

  • LauchedEffect: for this application I used it to handle navigation events. When you works with LaunchedEffect using key, the code inside LaunchedEffec only execute when the key changes. This is how it is used in my app
  • Coroutines: I use coroutine to call external services, Firebase Authentication. Althoug Firebase works with a listener and respond asyncronously, my ViewModel and the entire app use coroutines to make external calls. For this reason, I include the use of Coroutines inside Firebase. Another usage of coroutines was with the dispatcher; I used dispatcher.IO, because it is the appropriate dispatcher for making external service calls.
  • Clean Architecture: Currently, I use it to separate layer. Although I only have one module, the idea is to modify this architecture into a modular architecture later on. At present, there is a UI layer, a Domain layer, and Data later. Currently, they are are no mapper, but in the futere, I plan to include it.
  • Desing patterns: This app uses MVVM, the Strategic Pattern, the Repositoy Pattern, Dependency Injection Pattern, the Builder Pattern, and the Singleton Pattern. In another article, I will explain these importat parts of my application so you can sse how thtese patters are implemente
  • Flow: In this case, I only use Flow for UI because I understand it is not needed for other layers. The Flow I use is StatedFlow (MutalbeStateFlow) to send information to my UI so that it can react.

I want to express my heartfelt thanks to everyone reading this article. Your interest and time spent exploring my thoughts and experiences mean a lot to me. It’s your engagement and curiosity that inspire me to continue learning, sharing, and growing as a developer. I hope this article has provided you with valuable insights, and I look forward to any feedback or thoughts you may have. Thank you for being part of this journey!

Connect with Me

Thank you for taking the time to read this article! If you’d like to connect or explore more about my work, feel free to check out my LinkedIn and GitHub:

  • LinkedIn — Let’s connect and share ideas!
  • GitHub — Explore the code and projects I’m working on.

I’d love to hear your feedback or collaborate on exciting new projects!

--

--

Fabián Mondragón
Fabián Mondragón

Written by Fabián Mondragón

Android Architect and begginer iOS - Developer

No responses yet