Android Navigation Architecture Migration: Fragments as Navigation Owners

Summary

The Android Navigation Architecture is a powerful tool for managing navigation within Android applications. However, when using interfaces and implementing them within MainActivity, it can lead to a lot of application crashes. Transferring responsibility for navigation to individual fragments can help alleviate this issue, but it can also lead to cluttered code. In this article, we will explore the root cause of this problem, why it happens in real systems, and provide suggestions for organizing callbacks in fragments.

Root Cause

The root cause of this problem is the tight coupling between the navigation logic and the MainActivity. When the navigation logic is implemented within the MainActivity, it can lead to a God Object anti-pattern, where the MainActivity is responsible for managing all the navigation logic. This can make the code difficult to maintain and prone to errors.

Why This Happens in Real Systems

This problem occurs in real systems due to several reasons, including:

  • Lack of separation of concerns: When the navigation logic is not separated from the business logic, it can lead to a tight coupling between the two.
  • Insufficient use of architecture components: Not using architecture components such as ViewModel and LiveData can lead to a tight coupling between the navigation logic and the MainActivity.
  • Poor design patterns: Using poor design patterns such as the God Object anti-pattern can lead to a tight coupling between the navigation logic and the MainActivity.

Real-World Impact

The real-world impact of this problem can be significant, including:

  • Application crashes: A tight coupling between the navigation logic and the MainActivity can lead to application crashes.
  • Difficulty in maintaining the code: A tight coupling between the navigation logic and the MainActivity can make the code difficult to maintain.
  • Poor user experience: A tight coupling between the navigation logic and the MainActivity can lead to a poor user experience.

Example or Code

private val btnClickNavigationCallBack: () -> Unit = {
    val directions = HomeFragmentDirections.actionHomeFragmentToStoreFragment()
    findNavController().navigate(directions)
}

private val btn1ClickNavigationCallBack: () -> Unit = {
    val directions = HomeFragmentDirections.actionHomeFragmentToSmth1Fragment()
    findNavController().navigate(directions)
}

private val btn2ClickNavigationCallBack: () -> Unit = {
    val directions = HomeFragmentDirections.actionHomeFragmentToSmth2Fragment()
    findNavController().navigate(directions)
}

private val btn3ClickNavigationCallBack: () -> Unit = {
    val directions = HomeFragmentDirections.actionHomeFragmentToSmth3Fragment()
    findNavController().navigate(directions)
}

How Senior Engineers Fix It

Senior engineers fix this problem by:

  • Separating the navigation logic from the business logic: Using architecture components such as ViewModel and LiveData to separate the navigation logic from the business logic.
  • Using design patterns such as the Navigation Owner pattern: Using design patterns such as the Navigation Owner pattern to separate the navigation logic from the MainActivity.
  • Implementing the navigation logic within individual fragments: Implementing the navigation logic within individual fragments to reduce the tight coupling between the navigation logic and the MainActivity.

Why Juniors Miss It

Juniors may miss this problem due to:

  • Lack of experience: Juniors may not have the experience to recognize the tight coupling between the navigation logic and the MainActivity.
  • Insufficient knowledge of architecture components: Juniors may not have sufficient knowledge of architecture components such as ViewModel and LiveData to separate the navigation logic from the business logic.
  • Poor understanding of design patterns: Juniors may not have a good understanding of design patterns such as the Navigation Owner pattern to separate the navigation logic from the MainActivity.