|
16 | 16 | package com.google.firebase.dataconnect.minimaldemo
|
17 | 17 |
|
18 | 18 | import android.os.Bundle
|
19 |
| -import android.view.Menu |
20 |
| -import android.view.MenuItem |
21 |
| -import android.widget.CompoundButton.OnCheckedChangeListener |
| 19 | +import android.view.View |
22 | 20 | import androidx.activity.viewModels
|
23 | 21 | import androidx.appcompat.app.AppCompatActivity
|
24 |
| -import androidx.lifecycle.Lifecycle |
25 | 22 | import androidx.lifecycle.flowWithLifecycle
|
26 | 23 | import androidx.lifecycle.lifecycleScope
|
27 |
| -import com.google.firebase.dataconnect.minimaldemo.ListItemsViewModel.OperationState |
28 |
| -import com.google.firebase.dataconnect.minimaldemo.databinding.ActivityMainBinding |
| 24 | +import com.google.firebase.dataconnect.minimaldemo.databinding.ActivityListItemsBinding |
29 | 25 | import kotlinx.coroutines.flow.collectLatest
|
30 | 26 | import kotlinx.coroutines.launch
|
31 | 27 |
|
32 | 28 | class ListItemsActivity : AppCompatActivity() {
|
33 | 29 |
|
34 | 30 | private lateinit var myApplication: MyApplication
|
35 |
| - private lateinit var viewBinding: ActivityMainBinding |
| 31 | + private lateinit var viewBinding: ActivityListItemsBinding |
36 | 32 | private val viewModel: ListItemsViewModel by viewModels { ListItemsViewModel.Factory }
|
37 | 33 |
|
38 | 34 | override fun onCreate(savedInstanceState: Bundle?) {
|
39 | 35 | super.onCreate(savedInstanceState)
|
40 | 36 | myApplication = application as MyApplication
|
41 | 37 |
|
42 |
| - viewBinding = ActivityMainBinding.inflate(layoutInflater) |
| 38 | + viewBinding = ActivityListItemsBinding.inflate(layoutInflater) |
43 | 39 | setContentView(viewBinding.root)
|
44 | 40 |
|
45 |
| - viewBinding.insertItemButton.setOnClickListener { viewModel.insertItem() } |
46 |
| - viewBinding.getItemButton.setOnClickListener { viewModel.getItem() } |
47 |
| - viewBinding.deleteItemButton.setOnClickListener { viewModel.deleteItem() } |
48 |
| - viewBinding.useEmulatorCheckBox.setOnCheckedChangeListener(useEmulatorOnCheckedChangeListener) |
49 |
| - viewBinding.debugLoggingCheckBox.setOnCheckedChangeListener(debugLoggingOnCheckedChangeListener) |
50 |
| - |
51 | 41 | lifecycleScope.launch {
|
| 42 | + if (viewModel.loadingState == ListItemsViewModel.LoadingState.NotStarted) { |
| 43 | + viewModel.getItems() |
| 44 | + } |
52 | 45 | viewModel.stateSequenceNumber.flowWithLifecycle(lifecycle).collectLatest {
|
53 | 46 | onViewModelStateChange()
|
54 | 47 | }
|
55 | 48 | }
|
56 | 49 | }
|
57 | 50 |
|
58 |
| - override fun onCreateOptionsMenu(menu: Menu?): Boolean { |
59 |
| - menuInflater.inflate(R.menu.menu_main, menu) |
60 |
| - return true |
61 |
| - } |
62 |
| - |
63 |
| - override fun onOptionsItemSelected(item: MenuItem): Boolean { |
64 |
| - return super.onOptionsItemSelected(item) |
65 |
| - } |
66 |
| - |
67 |
| - override fun onResume() { |
68 |
| - super.onResume() |
69 |
| - lifecycleScope.launch { |
70 |
| - viewBinding.useEmulatorCheckBox.isChecked = myApplication.getUseDataConnectEmulator() |
71 |
| - viewBinding.debugLoggingCheckBox.isChecked = myApplication.getDataConnectDebugLoggingEnabled() |
72 |
| - } |
73 |
| - } |
74 |
| - |
75 | 51 | private fun onViewModelStateChange() {
|
76 |
| - viewBinding.progressText.text = viewModel.progressText |
77 |
| - viewBinding.insertItemButton.isEnabled = !viewModel.isInsertOperationInProgress |
78 |
| - viewBinding.getItemButton.isEnabled = |
79 |
| - viewModel.isGetOperationRunnable && !viewModel.isGetOperationInProgress |
80 |
| - viewBinding.deleteItemButton.isEnabled = |
81 |
| - viewModel.isDeleteOperationRunnable && !viewModel.isDeleteOperationInProgress |
82 |
| - } |
83 |
| - |
84 |
| - private val debugLoggingOnCheckedChangeListener = OnCheckedChangeListener { _, isChecked -> |
85 |
| - if (!lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) { |
86 |
| - return@OnCheckedChangeListener |
87 |
| - } |
88 |
| - myApplication.coroutineScope.launch { |
89 |
| - myApplication.setDataConnectDebugLoggingEnabled(isChecked) |
| 52 | + val items = viewModel.result?.getOrNull() |
| 53 | + val exception = viewModel.result?.exceptionOrNull() |
| 54 | + val loadingState = viewModel.loadingState |
| 55 | + |
| 56 | + if (loadingState == ListItemsViewModel.LoadingState.InProgress) { |
| 57 | + viewBinding.statusText.text = "Loading Items..." |
| 58 | + viewBinding.statusText.visibility = View.VISIBLE |
| 59 | + viewBinding.recyclerView.visibility = View.GONE |
| 60 | + } else if (items !== null) { |
| 61 | + viewBinding.statusText.text = "Items: $items" |
| 62 | + viewBinding.statusText.visibility = View.VISIBLE |
| 63 | + viewBinding.recyclerView.visibility = View.GONE |
| 64 | + } else if (exception !== null) { |
| 65 | + viewBinding.statusText.text = "Loading items FAILED: $exception" |
| 66 | + viewBinding.statusText.visibility = View.VISIBLE |
| 67 | + viewBinding.recyclerView.visibility = View.GONE |
| 68 | + } else { |
| 69 | + viewBinding.statusText.text = null |
| 70 | + viewBinding.statusText.visibility = View.GONE |
| 71 | + viewBinding.recyclerView.visibility = View.GONE |
90 | 72 | }
|
91 | 73 | }
|
92 |
| - |
93 |
| - private val useEmulatorOnCheckedChangeListener = OnCheckedChangeListener { _, isChecked -> |
94 |
| - if (!lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) { |
95 |
| - return@OnCheckedChangeListener |
96 |
| - } |
97 |
| - myApplication.coroutineScope.launch { myApplication.setUseDataConnectEmulator(isChecked) } |
98 |
| - } |
99 |
| - |
100 |
| - companion object { |
101 |
| - |
102 |
| - private val ListItemsViewModel.isInsertOperationInProgress: Boolean |
103 |
| - get() = insertState is OperationState.InProgress |
104 |
| - |
105 |
| - private val ListItemsViewModel.isGetOperationInProgress: Boolean |
106 |
| - get() = getState is OperationState.InProgress |
107 |
| - |
108 |
| - private val ListItemsViewModel.isDeleteOperationInProgress: Boolean |
109 |
| - get() = deleteState is OperationState.InProgress |
110 |
| - |
111 |
| - private val ListItemsViewModel.isGetOperationRunnable: Boolean |
112 |
| - get() = lastInsertedKey !== null |
113 |
| - |
114 |
| - private val ListItemsViewModel.isDeleteOperationRunnable: Boolean |
115 |
| - get() = lastInsertedKey !== null |
116 |
| - |
117 |
| - private val ListItemsViewModel.progressText: String? |
118 |
| - get() { |
119 |
| - // Save properties to local variables to enable Kotlin's type narrowing in the "if" blocks |
120 |
| - // below. |
121 |
| - val insertState = insertState |
122 |
| - val getState = getState |
123 |
| - val deleteState = deleteState |
124 |
| - val state = |
125 |
| - listOfNotNull(insertState, getState, deleteState).maxByOrNull { it.sequenceNumber } |
126 |
| - |
127 |
| - return if (state === null) { |
128 |
| - null |
129 |
| - } else if (state === insertState) { |
130 |
| - when (insertState) { |
131 |
| - is OperationState.InProgress -> |
132 |
| - "Inserting item: ${insertState.variables.toDisplayString()}" |
133 |
| - is OperationState.Completed -> |
134 |
| - insertState.result.fold( |
135 |
| - onSuccess = { |
136 |
| - "Inserted item with id=${it.id}:\n${insertState.variables.toDisplayString()}" |
137 |
| - }, |
138 |
| - onFailure = { "Inserting item ${insertState.variables} FAILED: $it" }, |
139 |
| - ) |
140 |
| - } |
141 |
| - } else if (state === getState) { |
142 |
| - when (getState) { |
143 |
| - is OperationState.InProgress -> "Retrieving item with ID ${getState.variables.id}..." |
144 |
| - is OperationState.Completed -> |
145 |
| - getState.result.fold( |
146 |
| - onSuccess = { |
147 |
| - "Retrieved item with ID ${getState.variables.id}:\n${it?.toDisplayString()}" |
148 |
| - }, |
149 |
| - onFailure = { "Retrieving item with ID ${getState.variables.id} FAILED: $it" }, |
150 |
| - ) |
151 |
| - } |
152 |
| - } else if (state === deleteState) { |
153 |
| - when (deleteState) { |
154 |
| - is OperationState.InProgress -> "Deleting item with ID ${deleteState.variables.id}..." |
155 |
| - is OperationState.Completed -> |
156 |
| - deleteState.result.fold( |
157 |
| - onSuccess = { "Deleted item with ID ${deleteState.variables.id}" }, |
158 |
| - onFailure = { "Deleting item with ID ${deleteState.variables.id} FAILED: $it" }, |
159 |
| - ) |
160 |
| - } |
161 |
| - } else { |
162 |
| - throw RuntimeException("internal error: unknown state: $state (error code vp4rjptx6r)") |
163 |
| - } |
164 |
| - } |
165 |
| - } |
166 | 74 | }
|
0 commit comments