Skip to main content

Introduction

NASA Explorer is built using modern Android development best practices, following a clean architecture approach that separates concerns across multiple layers. The app leverages Jetpack Compose for UI, Hilt for dependency injection, and Firebase for authentication and data persistence.

Architecture Layers

The application is structured in three main layers:
1

Presentation Layer (UI)

Contains Jetpack Compose screens and ViewModels that handle UI logic and state management. Each screen has a corresponding ViewModel that manages business logic and state.
2

Domain Layer

Defines the core business models used throughout the application. This layer is independent of frameworks and represents the business entities.
3

Data Layer

Manages data operations including API calls, authentication, and Firebase database interactions. Contains repositories, API services, and dependency injection modules.

Project Structure

com.ccandeladev.nasaexplorer/
├── MainActivity.kt              # Entry point
├── NasaExplorerApp.kt          # Application class with Hilt
├── data/
│   ├── api/
│   │   ├── NasaApiService.kt   # Retrofit API interface
│   │   ├── NasaRepository.kt   # Data repository
│   │   └── NasaResponse.kt     # API response models
│   ├── auth/
│   │   ├── AuthService.kt      # Firebase auth operations
│   │   └── AuthNetworkModule.kt # Auth DI module
│   └── di/
│       ├── ApiNetworkModule.kt  # Network DI module
│       └── FirebaseModule.kt    # Firebase DI module
├── domain/
│   ├── NasaModel.kt            # Core domain model
│   └── FavoriteNasaModel.kt    # Favorites model
└── ui/
    ├── core/
    │   ├── Routes.kt           # Navigation routes
    │   └── NasaExplorerNav.kt  # Navigation graph
    ├── homescreen/
    │   ├── HomeScreen.kt       # Home UI
    │   └── HomeScreenViewModel.kt # Home logic
    ├── dailyimagescreen/       # Daily image feature
    ├── randomimagescreen/      # Random images feature
    ├── rangeimagesscreen/      # Date range feature
    └── favoritesscreen/        # Favorites feature

Application Entry Point

The app initialization begins with the NasaExplorerApp class, which enables Hilt dependency injection:
NasaExplorerApp.kt
package com.ccandeladev.nasaexplorer

import android.app.Application
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp
class NasaExplorerApp: Application()
The @HiltAndroidApp annotation triggers Hilt’s code generation and enables dependency injection throughout the entire application lifecycle.
The MainActivity sets up the Compose UI and navigation:
MainActivity.kt
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            NASAExplorerTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    val navController = rememberNavController()
                    NasaExplorerNav(navHostController = navController)
                }
            }
        }
    }
}

Key Technologies

Jetpack Compose

Modern declarative UI framework for building native Android interfaces

Hilt / Dagger

Dependency injection framework for managing object creation and lifecycle

Kotlin Coroutines

Asynchronous programming for network calls and database operations

Firebase

Authentication and Realtime Database for user management and favorites

Retrofit

Type-safe HTTP client for NASA APOD API integration

Navigation Compose

Type-safe navigation between composable screens

Design Principles

Separation of Concerns

Each layer has a clear responsibility. UI components don’t directly access the network, and business logic is isolated in ViewModels.

Unidirectional Data Flow

Data flows from the data layer through ViewModels to the UI. User actions flow back down through callbacks.

Single Source of Truth

ViewModels hold the single source of truth for UI state using StateFlow, ensuring consistent UI updates.

Testability

Dependency injection and layer separation enable easy unit testing of individual components.

Architecture Diagram

Next Steps

MVVM Pattern

Learn how the MVVM pattern is implemented in NASA Explorer

Dependency Injection

Explore how Hilt manages dependencies across the app

Navigation

Understand the type-safe navigation system

Build docs developers (and LLMs) love