Skip to content

Commit

Permalink
generate-geodatabase-replica-from-feature-service: replace 4 state va…
Browse files Browse the repository at this point in the history
…riables by one UiState flow
  • Loading branch information
alan-edi committed Jan 13, 2025
1 parent bfa10e8 commit 7f87a0e
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@
package com.esri.arcgismaps.sample.generategeodatabasereplicafromfeatureservice.components

import android.app.Application
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.unit.IntSize
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
Expand All @@ -41,6 +37,8 @@ import com.arcgismaps.tasks.geodatabase.GeodatabaseSyncTask
import com.arcgismaps.toolkit.geoviewcompose.MapViewProxy
import com.esri.arcgismaps.sample.sampleslib.components.MessageDialogViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import java.io.File

Expand Down Expand Up @@ -95,19 +93,9 @@ class GenerateGeodatabaseReplicaFromFeatureServiceViewModel(
// a message dialog view model for handling error messages
val messageDialogVM = MessageDialogViewModel()

// job progress dialog visibility state
var showJobProgressDialog by mutableStateOf(false)
private set

// job progress percentage
var jobProgress by mutableIntStateOf(0)
private set

// state variables indicating if the buttons are enabled
var resetButtonEnabled by mutableStateOf(false)
private set
var generateButtonEnabled by mutableStateOf(false)
private set
// state flow to expose current UI state to UI
private val _uiStateFlow = MutableStateFlow(UiState(status = UiStatus.STARTING))
val uiStateFlow = _uiStateFlow.asStateFlow()

// create a GeodatabaseSyncTask with the URL of the feature service
private var geodatabaseSyncTask = GeodatabaseSyncTask(FEATURE_SERVICE_URL)
Expand All @@ -127,7 +115,7 @@ class GenerateGeodatabaseReplicaFromFeatureServiceViewModel(
arcGISMap.load().onSuccess {
// load the GeodatabaseSyncTask
geodatabaseSyncTask.load().onSuccess {
generateButtonEnabled = true
_uiStateFlow.value = UiState(status = UiStatus.READY_FOR_GENERATE)
}.onFailure { error ->
messageDialogVM.showMessageDialog(
title = "Failed to load GeodatabaseSyncTask",
Expand Down Expand Up @@ -187,17 +175,14 @@ class GenerateGeodatabaseReplicaFromFeatureServiceViewModel(
arcGISMap.operationalLayers.add(featureLayer)
// close the current geodatabase, if a replica was already generated
geodatabase?.close()
// show the Generate button
generateButtonEnabled = true
resetButtonEnabled = false
_uiStateFlow.value = UiState(status = UiStatus.READY_FOR_GENERATE)
}

/**
* Generate the geodatabase replica.
*/
fun generateGeodatabaseReplica() {
// disable the Generate button
generateButtonEnabled = false
_uiStateFlow.value = UiState(status = UiStatus.GENERATING, jobProgress = 0)

val offlineGeodatabasePath =
application.getExternalFilesDir(null)?.path + "/portland_trees_gdb.geodatabase"
Expand Down Expand Up @@ -250,18 +235,14 @@ class GenerateGeodatabaseReplicaFromFeatureServiceViewModel(
// create a flow-collection for the job's progress
viewModelScope.launch(Dispatchers.Main) {
job.progress.collect { progress ->
jobProgress = progress
_uiStateFlow.value = UiState(status = UiStatus.GENERATING, jobProgress = progress)
}
}

// show the Job Progress Dialog
showJobProgressDialog = true

// start the job and wait for Job result
job.start()
job.result().onSuccess { geodatabase ->
// dismiss the progress dialog and display the data
showJobProgressDialog = false
// display the data
loadGeodatabaseAndAddToMap(geodatabase)

// unregister the geodatabase since we will not sync changes to the service
Expand All @@ -272,12 +253,11 @@ class GenerateGeodatabaseReplicaFromFeatureServiceViewModel(
)
}
}.onFailure { error ->
_uiStateFlow.value = UiState(status = UiStatus.READY_FOR_GENERATE)
messageDialogVM.showMessageDialog(
title = "Error generating geodatabase",
description = error.message.toString()
)
showJobProgressDialog = false
generateButtonEnabled = true
}
}

Expand All @@ -297,13 +277,14 @@ class GenerateGeodatabaseReplicaFromFeatureServiceViewModel(
}
// keep track of the geodatabase to close it before generating a new replica
geodatabase = replicaGeodatabase
_uiStateFlow.value = UiState(status = UiStatus.REPLICA_DISPLAYED)
}.onFailure { error ->
_uiStateFlow.value = UiState(status = UiStatus.READY_FOR_GENERATE)
messageDialogVM.showMessageDialog(
title = "Error loading geodatabase",
description = error.message.toString()
)
}
resetButtonEnabled = true
}

/**
Expand All @@ -313,7 +294,7 @@ class GenerateGeodatabaseReplicaFromFeatureServiceViewModel(
viewModelScope.launch(Dispatchers.IO) {
generateGeodatabaseJob?.cancel()
}
generateButtonEnabled = true
_uiStateFlow.value = UiState(status = UiStatus.READY_FOR_GENERATE)
}

override fun onCleared() {
Expand All @@ -322,3 +303,18 @@ class GenerateGeodatabaseReplicaFromFeatureServiceViewModel(
geodatabase?.close()
}
}

/**
* Data class representing the UI state.
*/
data class UiState(
val status: UiStatus,
val jobProgress: Int = 0
)

enum class UiStatus {
STARTING,
READY_FOR_GENERATE,
GENERATING,
REPLICA_DISPLAYED
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,19 @@ import androidx.compose.material3.Button
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat.getString
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import com.arcgismaps.LoadStatus
import com.arcgismaps.toolkit.geoviewcompose.MapView
import com.esri.arcgismaps.sample.generategeodatabasereplicafromfeatureservice.components.GenerateGeodatabaseReplicaFromFeatureServiceViewModel
import com.esri.arcgismaps.sample.generategeodatabasereplicafromfeatureservice.R
import com.esri.arcgismaps.sample.generategeodatabasereplicafromfeatureservice.components.UiStatus
import com.esri.arcgismaps.sample.sampleslib.components.JobLoadingDialog
import com.esri.arcgismaps.sample.sampleslib.components.MessageDialog
import com.esri.arcgismaps.sample.sampleslib.components.SampleTopAppBar
Expand All @@ -47,6 +50,7 @@ import com.esri.arcgismaps.sample.sampleslib.components.SampleTopAppBar
fun GenerateGeodatabaseReplicaFromFeatureServiceScreen(sampleName: String) {
val application = LocalContext.current.applicationContext
val mapViewModel: GenerateGeodatabaseReplicaFromFeatureServiceViewModel = viewModel()
val uiState by mapViewModel.uiStateFlow.collectAsStateWithLifecycle()
Scaffold(
topBar = { SampleTopAppBar(title = sampleName) },
content = {
Expand Down Expand Up @@ -90,7 +94,7 @@ fun GenerateGeodatabaseReplicaFromFeatureServiceScreen(sampleName: String) {
onClick = {
mapViewModel.resetMap()
},
enabled = mapViewModel.resetButtonEnabled
enabled = uiState.status == UiStatus.REPLICA_DISPLAYED
) {
Text(text = getString(application, R.string.reset_map))
}
Expand All @@ -99,17 +103,17 @@ fun GenerateGeodatabaseReplicaFromFeatureServiceScreen(sampleName: String) {
onClick = {
mapViewModel.generateGeodatabaseReplica()
},
enabled = mapViewModel.generateButtonEnabled
enabled = uiState.status == UiStatus.READY_FOR_GENERATE
) {
Text(text = getString(application, R.string.generate_button_text))
}
}

// display progress dialog while generating a geodatabase replica
if (mapViewModel.showJobProgressDialog) {
if (uiState.status == UiStatus.GENERATING) {
JobLoadingDialog(
title = getString(application, R.string.dialog_title),
progress = mapViewModel.jobProgress,
progress = uiState.jobProgress,
cancelJobRequest = { mapViewModel.cancelOfflineGeodatabaseJob() }
)
}
Expand Down

0 comments on commit 7f87a0e

Please sign in to comment.