Skip to content

Instantly share code, notes, and snippets.

@Debdutta-Panda
Created June 3, 2022 15:58
Show Gist options
  • Save Debdutta-Panda/2de33ea5e2f801d37450b7f839a9b5bb to your computer and use it in GitHub Desktop.
Save Debdutta-Panda/2de33ea5e2f801d37450b7f839a9b5bb to your computer and use it in GitHub Desktop.
Jetpack Compose Navigation with MVVM
package com.debduttapanda.powernavigation
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import com.debduttapanda.powernavigation.ui.theme.PowerNavigationTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val pageAViewModel: PageAViewModel by viewModels()
val pageBViewModel: PageBViewModel by viewModels()
setContent {
PowerNavigationTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
Text(
"With MVVM",
fontSize = 24.sp,
color = Color(0xfff44336),
fontWeight = FontWeight.Bold
)
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "page_a"){
composable(
"page_a"
){
PageA(navController,pageAViewModel)
}
composable(
"page_b/{money}?bonus={bonus}",
arguments = listOf(
navArgument("money"){
type = NavType.IntType
},
navArgument("bonus"){
type = NavType.IntType
defaultValue = 0
}
)
){backStackEntry->
PageB(
navController,
pageBViewModel,
backStackEntry.arguments?.getInt("money"),
backStackEntry.arguments?.getInt("bonus"),
)
}
}
}
}
}
}
}
package com.debduttapanda.powernavigation
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.sp
import androidx.navigation.NavHostController
@Composable
fun PageA(navController: NavHostController, pageAViewModel: PageAViewModel) {
LaunchedEffect(key1 = pageAViewModel.navigationTrigger.value){
if(pageAViewModel.navigationTrigger.value==0L){
return@LaunchedEffect
}
navController
.currentBackStackEntry
?.savedStateHandle
?.remove<Int>("totalReceived")
if(!pageAViewModel.sendBonus.value){
navController.navigate("page_b/${pageAViewModel.money.value}")
}
else{
navController.navigate("page_b/${pageAViewModel.money.value}?bonus=50")
}
pageAViewModel.onNavigated()
}
val result = navController
.currentBackStackEntry
?.savedStateHandle
?.getLiveData<Int>("totalReceived")?.observeAsState()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
){
TextField(
value = pageAViewModel.money.value.toString(),
onValueChange = {
try {
pageAViewModel.money.value = it.toInt()
} catch (e: Exception) {
pageAViewModel.money.value = 0
}
},
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Number
)
)
Row(
verticalAlignment = Alignment.CenterVertically
){
Text("Bonus")
Checkbox(
checked = pageAViewModel.sendBonus.value,
onCheckedChange = {
pageAViewModel.sendBonus.value = it
}
)
}
Text(
"Page A: Send Money",
color = Color(0xfff44336),
fontSize = 24.sp,
fontWeight = FontWeight.Bold
)
Button(
onClick = {
pageAViewModel.onSendClick()
},
colors = ButtonDefaults.buttonColors(
backgroundColor = Color(0xfff44336),
contentColor = Color.White
)
) {
Text("Send Money")
}
if((result?.value?:0)>0){
Text("Acknowledgement of ${result?.value} received")
}
}
}
package com.debduttapanda.powernavigation
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
class PageAViewModel: ViewModel() {
val money = mutableStateOf(0)
val sendBonus = mutableStateOf(false)
val navigationTrigger = mutableStateOf(0L)
fun onSendClick() {
navigationTrigger.value = System.currentTimeMillis()
}
fun onNavigated() {
navigationTrigger.value = 0L
}
}
package com.debduttapanda.powernavigation
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
import androidx.navigation.NavHostController
@Composable
fun PageB(
navController: NavHostController,
pageBViewModel: PageBViewModel,
receivedMoney: Int?,
bonus: Int?
) {
LaunchedEffect(key1 = pageBViewModel.navigationTrigger.value){
if(pageBViewModel.navigationTrigger.value==0L){
return@LaunchedEffect
}
navController
.previousBackStackEntry
?.savedStateHandle
?.set("totalReceived",(receivedMoney?:0)+(bonus?:0))
navController.navigateUp()
pageBViewModel.onNavigated()
}
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
){
Text(
"Page B: received money $receivedMoney ${if((bonus?:0)>0) "got $bonus bonus" else "): no bonus this month"}",
color = Color(0xfff44336),
fontSize = 24.sp,
fontWeight = FontWeight.Bold
)
Button(
onClick = {
pageBViewModel.onGoBack()
},
colors = ButtonDefaults.buttonColors(
backgroundColor = Color(0xfff44336),
contentColor = Color.White
)
) {
Text("Go back and pay me again")
}
}
}
package com.debduttapanda.powernavigation
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
class PageBViewModel: ViewModel() {
val navigationTrigger = mutableStateOf(0L)
fun onGoBack() {
navigationTrigger.value = System.currentTimeMillis()
}
fun onNavigated() {
navigationTrigger.value = 0L
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment