diff --git a/app/build.gradle.kts b/app/build.gradle.kts index b9008c7..afdbcd9 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -66,7 +66,7 @@ android { dependencies { // Import the Compose BOM - implementation(platform("androidx.compose:compose-bom:2024.11.00")) + implementation(platform("androidx.compose:compose-bom:2024.12.01")) implementation("androidx.activity:activity-compose:1.9.3") implementation("androidx.compose.material3:material3") implementation("androidx.compose.ui:ui") @@ -74,7 +74,7 @@ dependencies { implementation("androidx.compose.ui:ui-tooling-preview") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.7") implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.7") - implementation("androidx.navigation:navigation-compose:2.8.4") + implementation("androidx.navigation:navigation-compose:2.8.5") //Room implementation("androidx.room:room-runtime:${rootProject.extra["room_version"]}") diff --git a/app/src/main/java/com/example/inventory/ui/item/ItemDetailsScreen.kt b/app/src/main/java/com/example/inventory/ui/item/ItemDetailsScreen.kt index caab418..65b3767 100644 --- a/app/src/main/java/com/example/inventory/ui/item/ItemDetailsScreen.kt +++ b/app/src/main/java/com/example/inventory/ui/item/ItemDetailsScreen.kt @@ -48,7 +48,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier @@ -64,7 +63,6 @@ import com.example.inventory.data.Item import com.example.inventory.ui.AppViewModelProvider import com.example.inventory.ui.navigation.NavigationDestination import com.example.inventory.ui.theme.InventoryTheme -import kotlinx.coroutines.launch object ItemDetailsDestination : NavigationDestination { override val route = "item_details" @@ -82,7 +80,6 @@ fun ItemDetailsScreen( viewModel: ItemDetailsViewModel = viewModel(factory = AppViewModelProvider.Factory) ) { val uiState = viewModel.uiState.collectAsState() - val coroutineScope = rememberCoroutineScope() Scaffold( topBar = { InventoryTopAppBar( @@ -113,14 +110,8 @@ fun ItemDetailsScreen( itemDetailsUiState = uiState.value, onSellItem = { viewModel.reduceQuantityByOne() }, onDelete = { - // Note: If the user rotates the screen very fast, the operation may get cancelled - // and the item may not be deleted from the Database. This is because when config - // change occurs, the Activity will be recreated and the rememberCoroutineScope will - // be cancelled - since the scope is bound to composition. - coroutineScope.launch { viewModel.deleteItem() navigateBack() - } }, modifier = Modifier .padding( diff --git a/app/src/main/java/com/example/inventory/ui/item/ItemDetailsViewModel.kt b/app/src/main/java/com/example/inventory/ui/item/ItemDetailsViewModel.kt index c37b0f5..377fe6a 100644 --- a/app/src/main/java/com/example/inventory/ui/item/ItemDetailsViewModel.kt +++ b/app/src/main/java/com/example/inventory/ui/item/ItemDetailsViewModel.kt @@ -20,6 +20,7 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.example.inventory.data.ItemsRepository +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.filterNotNull @@ -67,8 +68,10 @@ class ItemDetailsViewModel( /** * Deletes the item from the [ItemsRepository]'s data source. */ - suspend fun deleteItem() { - itemsRepository.deleteItem(uiState.value.itemDetails.toItem()) + fun deleteItem() { + viewModelScope.launch(Dispatchers.IO) { + itemsRepository.deleteItem(uiState.value.itemDetails.toItem()) + } } companion object { diff --git a/app/src/main/java/com/example/inventory/ui/item/ItemEditScreen.kt b/app/src/main/java/com/example/inventory/ui/item/ItemEditScreen.kt index e290a3c..34b1ba9 100644 --- a/app/src/main/java/com/example/inventory/ui/item/ItemEditScreen.kt +++ b/app/src/main/java/com/example/inventory/ui/item/ItemEditScreen.kt @@ -24,7 +24,6 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.res.stringResource @@ -35,7 +34,6 @@ import com.example.inventory.R import com.example.inventory.ui.AppViewModelProvider import com.example.inventory.ui.navigation.NavigationDestination import com.example.inventory.ui.theme.InventoryTheme -import kotlinx.coroutines.launch object ItemEditDestination : NavigationDestination { override val route = "item_edit" @@ -52,7 +50,6 @@ fun ItemEditScreen( modifier: Modifier = Modifier, viewModel: ItemEditViewModel = viewModel(factory = AppViewModelProvider.Factory) ) { - val coroutineScope = rememberCoroutineScope() Scaffold( topBar = { InventoryTopAppBar( @@ -67,14 +64,8 @@ fun ItemEditScreen( itemUiState = viewModel.itemUiState, onItemValueChange = viewModel::updateUiState, onSaveClick = { - // Note: If the user rotates the screen very fast, the operation may get cancelled - // and the item may not be updated in the Database. This is because when config - // change occurs, the Activity will be recreated and the rememberCoroutineScope will - // be cancelled - since the scope is bound to composition. - coroutineScope.launch { viewModel.updateItem() navigateBack() - } }, modifier = Modifier .padding( diff --git a/app/src/main/java/com/example/inventory/ui/item/ItemEditViewModel.kt b/app/src/main/java/com/example/inventory/ui/item/ItemEditViewModel.kt index bdd6491..f33a6a6 100644 --- a/app/src/main/java/com/example/inventory/ui/item/ItemEditViewModel.kt +++ b/app/src/main/java/com/example/inventory/ui/item/ItemEditViewModel.kt @@ -23,6 +23,7 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.example.inventory.data.ItemsRepository +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch @@ -55,9 +56,10 @@ class ItemEditViewModel( /** * Update the item in the [ItemsRepository]'s data source */ - suspend fun updateItem() { - if (validateInput(itemUiState.itemDetails)) { - itemsRepository.updateItem(itemUiState.itemDetails.toItem()) + fun updateItem() { + viewModelScope.launch(Dispatchers.IO) { + if (validateInput()) + itemsRepository.updateItem(itemUiState.itemDetails.toItem()) } } diff --git a/app/src/main/java/com/example/inventory/ui/item/ItemEntryScreen.kt b/app/src/main/java/com/example/inventory/ui/item/ItemEntryScreen.kt index e542de8..e782831 100644 --- a/app/src/main/java/com/example/inventory/ui/item/ItemEntryScreen.kt +++ b/app/src/main/java/com/example/inventory/ui/item/ItemEntryScreen.kt @@ -33,7 +33,6 @@ import androidx.compose.material3.OutlinedTextFieldDefaults import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.res.dimensionResource @@ -46,7 +45,6 @@ import com.example.inventory.R import com.example.inventory.ui.AppViewModelProvider import com.example.inventory.ui.navigation.NavigationDestination import com.example.inventory.ui.theme.InventoryTheme -import kotlinx.coroutines.launch import java.util.Currency import java.util.Locale @@ -63,7 +61,6 @@ fun ItemEntryScreen( canNavigateBack: Boolean = true, viewModel: ItemEntryViewModel = viewModel(factory = AppViewModelProvider.Factory) ) { - val coroutineScope = rememberCoroutineScope() Scaffold( topBar = { InventoryTopAppBar( @@ -77,14 +74,8 @@ fun ItemEntryScreen( itemUiState = viewModel.itemUiState, onItemValueChange = viewModel::updateUiState, onSaveClick = { - // Note: If the user rotates the screen very fast, the operation may get cancelled - // and the item may not be saved in the Database. This is because when config - // change occurs, the Activity will be recreated and the rememberCoroutineScope will - // be cancelled - since the scope is bound to composition. - coroutineScope.launch { viewModel.saveItem() navigateBack() - } }, modifier = Modifier .padding( diff --git a/app/src/main/java/com/example/inventory/ui/item/ItemEntryViewModel.kt b/app/src/main/java/com/example/inventory/ui/item/ItemEntryViewModel.kt index 9729464..3a156f4 100644 --- a/app/src/main/java/com/example/inventory/ui/item/ItemEntryViewModel.kt +++ b/app/src/main/java/com/example/inventory/ui/item/ItemEntryViewModel.kt @@ -20,8 +20,11 @@ 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.inventory.data.Item import com.example.inventory.data.ItemsRepository +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch import java.text.NumberFormat /** @@ -47,9 +50,10 @@ class ItemEntryViewModel(private val itemsRepository: ItemsRepository) : ViewMod /** * Inserts an [Item] in the Room database */ - suspend fun saveItem() { - if (validateInput()) { - itemsRepository.insertItem(itemUiState.itemDetails.toItem()) + fun saveItem() { + viewModelScope.launch(Dispatchers.IO) { + if (validateInput()) + itemsRepository.insertItem(itemUiState.itemDetails.toItem()) } } diff --git a/build.gradle.kts b/build.gradle.kts index bc180f5..554d9bd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -22,12 +22,12 @@ buildscript { } plugins { - id("com.android.application") version "8.1.4" apply false - id("com.android.library") version "8.1.4" apply false + id("com.android.application") version "8.7.3" apply false + id("com.android.library") version "8.7.3" apply false id("org.jetbrains.kotlin.android") version "2.1.0" apply false id("org.jetbrains.kotlin.plugin.compose") version "2.1.0" apply false } tasks.register("clean", Delete::class) { - delete(rootProject.buildDir) + delete(rootProject.layout.buildDirectory) }