Part 3 : Implementing NavGraph in app

Mohit Damke
3 min readJul 4, 2024

--

Implement NavGraph for better navigation in app and there will be no crashes

For better understanding of the navigation check out this article

Implementing NavGraph Navigation

  • First you need to create the package name as “Navigation” in the project.
  • Then you have to first define routes of the screens.
package com.example.newsapp.presentation.navgraph

sealed class Route(val route: String) {

object OnBoardingScreen : Route(route = "onBoardingScreen")

object HomeScreen : Route(route = "homeScreen")

object SearchScreen : Route(route = "searchScreen")

object BookmarkScreen : Route(route = "bookMarkScreen")

object DetailsScreen : Route(route = "detailsScreen")

object AppStartNavigation : Route(route = "appStartNavigation")

object NewsNavigation : Route(route = "newsNavigation")

object NewsNavigatorScreen : Route(route = "newsNavigator")

}
  • Here i have define routes in a sealed class.
  • After that you have to define the Navigation Controller.

Navigation

package com.example.newsapp.presentation.navgraph

import androidx.compose.runtime.Composable
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navigation
import androidx.paging.compose.collectAsLazyPagingItems
import com.example.newsapp.presentation.bookmark.BookmarkScreen
import com.example.newsapp.presentation.bookmark.BookmarkViewModel
import com.example.newsapp.presentation.home.HomeScreen
import com.example.newsapp.presentation.home.HomeViewModel
import com.example.newsapp.presentation.news_navigation.NewsNavigator
import com.example.newsapp.presentation.onboarding.OnBoardingViewModel
import com.example.newsapp.presentation.onboarding.components.OnBoardingScreen
import com.example.newsapp.presentation.search.SearchScreen
import com.example.newsapp.presentation.search.SearchViewModel

@Composable
fun NavGraph(
startDestination: String
) {
val navController = rememberNavController()

NavHost(navController = navController, startDestination = startDestination) {
navigation(
route = Route.AppStartNavigation.route,
startDestination = Route.OnBoardingScreen.route
) {
composable(route = Route.OnBoardingScreen.route) {
val viewModel: OnBoardingViewModel = hiltViewModel()
OnBoardingScreen(event = viewModel::onEvent)
}
}

navigation(
route = Route.NewsNavigation.route,
startDestination = Route.NewsNavigatorScreen.route
) {
composable(route = Route.NewsNavigatorScreen.route) {
NewsNavigator()

}
}


}


}
  • Here is the format of the navigation which distributed through graphs

Implementing logic for user open an app

  • Here we have onboarding screen and after clicking on get started in onboarding screen we will land on the home page.
  • So if the user have click on get started button once then after he again opens an app so will not land on onboarding screen rather he will bypass it and land on Home Screen (News Feed Screen).
package com.example.newsapp

import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.newsapp.domain.usecases.app_entry.AppEntryUseCases
import com.example.newsapp.presentation.navgraph.Route
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import javax.inject.Inject

@HiltViewModel
class MainViewModel @Inject constructor(
private val appEntryUseCases: AppEntryUseCases
) :
ViewModel() {

var splashCondition by mutableStateOf(true)
private set

var startDestination by mutableStateOf(Route.AppStartNavigation.route)
private set

init {
appEntryUseCases.readAppEntry().onEach { shouldStartFromHomeScreen ->
if (shouldStartFromHomeScreen) {
startDestination = Route.NewsNavigation.route
} else {
startDestination = Route.AppStartNavigation.route
}
delay(300)
splashCondition = false
}.launchIn(viewModelScope)
}
}
  • So here we have described Splash Condition as true.
  • And describe start destination as AppStartNavigation which means that the app start from the splash screen.
  • Make sure to apply launchIn(viewModelScope)
  • And apply one init in which we initialize one condition where appEntryUseCases.readAppEntry().onEach
  • If it will become true then we will navigate to Home Screen.
  • if false then we will navigate to OnBoarding Screen.

Check for the result

package com.example.newsapp

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.material3.MaterialTheme
import androidx.compose.ui.Modifier
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.lifecycleScope
import com.example.newsapp.data.local.NewsDao
import com.example.newsapp.domain.model.Article
import com.example.newsapp.domain.model.Source
import com.example.newsapp.presentation.navgraph.NavGraph
import com.example.newsapp.presentation.onboarding.OnBoardingViewModel
import com.example.newsapp.presentation.onboarding.components.OnBoardingScreen
import com.example.newsapp.ui.theme.NewsAppTheme
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import javax.inject.Inject

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
private val viewModel by viewModels<MainViewModel>()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()


installSplashScreen().apply {
setKeepOnScreenCondition {
viewModel.splashCondition
}
}
getActionBar()?.hide();
setContent {
NewsAppTheme {
Box(
modifier = Modifier.background(MaterialTheme.colorScheme.background)
) {
val startDestination = viewModel.startDestination
NavGraph(startDestination = startDestination)
}
}
}
}
}
  • Add NavGraph in the MainActivity and initialize the viewmodel in it.
  • Create a variable for startDestination.
  • Also Apply Splash Condition so that splash screen will takes place for 0.3 sec and after that next page will appear.

We are now able to implement the app entry point as the user first login into app the onboarding screen will be visible and after 2nd time login into app the home screen will be visible rather than onboarding screen.

If you have not read Part 2 of the series the here is the link below

You can visit the introduction article for the news app with the link below

Visit my GitHub Repository : https://github.com/mohitdamke/NewsApp

Make sure to follow me on
Link-tree :
https://linktr.ee/MohitDamke01
LinkedIn :
https://www.linkedin.com/in/mohitdamke01

--

--

Mohit Damke

Junior Android Developer | Kotlin | Jetpack | Firebase | Android Studio | MVVM & Clean Code Architecture