Skip to content

Commit 8e82b68

Browse files
committed
Use compose state instead of live data
1 parent 1595f10 commit 8e82b68

File tree

3 files changed

+59
-83
lines changed

3 files changed

+59
-83
lines changed

src/app/src/main/java/com/couchbase/learningpath/ui/MainActivity.kt

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import androidx.activity.ComponentActivity
66
import androidx.activity.compose.setContent
77
import androidx.compose.material.*
88
import androidx.compose.runtime.*
9-
import androidx.compose.runtime.livedata.observeAsState
109
import androidx.compose.ui.Modifier
1110
import androidx.compose.ui.platform.LocalLifecycleOwner
1211
import androidx.compose.ui.res.stringResource
@@ -80,19 +79,13 @@ class MainActivity : ComponentActivity() {
8079
drawerState = drawerState,
8180
gesturesEnabled = drawerState.isOpen,
8281
drawerContent = {
83-
val givenName by profileViewModel.givenName.observeAsState()
84-
val surname by profileViewModel.surname.observeAsState()
85-
val emailAddress by profileViewModel.emailAddress.observeAsState()
86-
val team by profileViewModel.team.observeAsState()
87-
val profilePic by profileViewModel.profilePic.observeAsState()
88-
8982
Drawer(
9083
modifier = Modifier.semantics { contentDescription = "{$menuResource}1" },
91-
firstName = givenName,
92-
lastName = surname,
93-
email = emailAddress,
94-
team = team,
95-
profilePicture = profilePic,
84+
firstName = profileViewModel.givenName,
85+
lastName = profileViewModel.surname,
86+
email = profileViewModel.emailAddress,
87+
team = profileViewModel.team,
88+
profilePicture = profileViewModel.profilePic,
9689
onClicked = { route ->
9790
scope.launch {
9891
drawerState.close()

src/app/src/main/java/com/couchbase/learningpath/ui/profile/UserProfileView.kt

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import androidx.compose.material.*
1818
import androidx.compose.material.icons.Icons
1919
import androidx.compose.material.icons.filled.Menu
2020
import androidx.compose.runtime.*
21-
import androidx.compose.runtime.livedata.observeAsState
2221
import androidx.compose.ui.Alignment
2322
import androidx.compose.ui.Modifier
2423
import androidx.compose.ui.draw.clip
@@ -45,14 +44,6 @@ fun UserProfileView(
4544
scaffoldState: ScaffoldState = rememberScaffoldState(),
4645
viewModel: UserProfileViewModel
4746
) {
48-
val givenName by viewModel.givenName.observeAsState("")
49-
val surname by viewModel.surname.observeAsState("")
50-
val jobTitle by viewModel.jobTitle.observeAsState("")
51-
val profilePic by viewModel.profilePic.observeAsState()
52-
val emailAddress by viewModel.emailAddress.observeAsState("")
53-
val team by viewModel.team.observeAsState("")
54-
val toastMessage by viewModel.toastMessage.observeAsState()
55-
5647
LearningPathTheme {
5748
// A surface container using the 'background' color from the theme
5849
Scaffold(scaffoldState = scaffoldState,
@@ -65,20 +56,19 @@ fun UserProfileView(
6556
Surface(
6657
color = MaterialTheme.colors.background,
6758
modifier = Modifier.fillMaxSize()
68-
)
69-
{
59+
) {
7060
UserProfileFormWidget(
71-
givenName,
61+
viewModel.givenName,
7262
viewModel.onGivenNameChanged,
73-
surname,
63+
viewModel.surname,
7464
viewModel.onSurnameChanged,
75-
jobTitle,
65+
viewModel.jobTitle,
7666
viewModel.onJobTitleChanged,
77-
profilePic,
67+
viewModel.profilePic,
7868
viewModel.onProfilePicChanged,
79-
emailAddress,
80-
team,
81-
toastMessage,
69+
viewModel.emailAddress,
70+
viewModel.team,
71+
viewModel.toastMessage,
8272
viewModel.onSave,
8373
viewModel.clearToastMessage
8474
)

src/app/src/main/java/com/couchbase/learningpath/ui/profile/UserProfileViewModel.kt

Lines changed: 46 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import android.app.Application
44
import android.graphics.Bitmap
55
import android.graphics.BitmapFactory
66
import android.graphics.drawable.Drawable
7+
import androidx.compose.runtime.getValue
8+
import androidx.compose.runtime.mutableStateOf
9+
import androidx.compose.runtime.setValue
710
import androidx.core.graphics.drawable.toBitmap
8-
import androidx.lifecycle.LiveData
9-
import androidx.lifecycle.MutableLiveData
10-
import androidx.lifecycle.Observer
1111
import androidx.lifecycle.AndroidViewModel
1212
import androidx.lifecycle.viewModelScope
1313
import com.couchbase.lite.Blob
@@ -28,112 +28,105 @@ class UserProfileViewModel(
2828
) : AndroidViewModel(application) {
2929

3030
//track our fields in our composable
31-
private val _givenName = MutableLiveData("")
32-
val givenName: LiveData<String> = _givenName
31+
var givenName by mutableStateOf("")
32+
private set
3333

34-
private val _surname = MutableLiveData("")
35-
val surname: LiveData<String> = _surname
34+
var surname by mutableStateOf("")
35+
private set
3636

37-
private val _jobTitle = MutableLiveData("")
38-
val jobTitle: LiveData<String> = _jobTitle
37+
var jobTitle by mutableStateOf("")
38+
private set
3939

40-
private val _emailAddress = MutableLiveData("")
41-
val emailAddress: LiveData<String> = _emailAddress
40+
var emailAddress by mutableStateOf("")
41+
private set
4242

43-
private val _team = MutableLiveData("")
44-
val team: LiveData<String> = _team
43+
var team by mutableStateOf("")
44+
private set
4545

46-
private val _toastMessage = MutableLiveData("")
47-
val toastMessage: LiveData<String> = _toastMessage
46+
var toastMessage by mutableStateOf("")
47+
private set
4848

49-
private val _profilePic = MutableLiveData<Bitmap?>(null)
50-
val profilePic: LiveData<Bitmap?> = _profilePic
49+
var profilePic by mutableStateOf(defaultProfilePic())
50+
private set
51+
52+
private fun defaultProfilePic(): Bitmap {
53+
return BitmapFactory.decodeResource(getApplication<Application>().resources, R.drawable.profile_placeholder)
54+
}
5155

5256
private val userObserver: (User?) -> Unit = { currentUser ->
5357
currentUser?.let { authenticatedUser ->
54-
_emailAddress.value = authenticatedUser.username
55-
_team.value = authenticatedUser.team
58+
emailAddress = authenticatedUser.username
59+
team = authenticatedUser.team
5660
//when getting information from the database need to make sure
5761
//to use Dispatchers.IO so that Disk I/O work isn't done on the main thread
5862
viewModelScope.launch(Dispatchers.IO) {
5963
val userProfile = repository.get(authenticatedUser.username)
6064
//make sure when we update the UI we update on the Main Thread
6165
withContext(Dispatchers.Main) {
62-
userProfile["givenName"]?.let {
63-
_givenName.value = userProfile["givenName"] as String
64-
}
65-
userProfile["surname"]?.let {
66-
_surname.value = userProfile["surname"] as String
67-
}
68-
userProfile["jobTitle"]?.let {
69-
_jobTitle.value = userProfile["jobTitle"] as String
70-
}
71-
userProfile["imageData"]?.let {
72-
val blob = userProfile["imageData"] as Blob
66+
givenName = userProfile["givenName"] as? String ?: ""
67+
surname = userProfile["surname"] as? String ?: ""
68+
jobTitle = userProfile["jobTitle"] as? String ?: ""
69+
profilePic = (userProfile["imageData"] as? Blob)?.let { blob ->
7370
val d = Drawable.createFromStream(blob.contentStream, "res")
74-
_profilePic.value = d?.toBitmap()
75-
}
71+
d?.toBitmap()
72+
} ?: defaultProfilePic()
7673
}
7774
}
7875
}
7976
}
8077

8178
init {
8279
authService.currentUser.observeForever(userObserver)
83-
_profilePic.value = BitmapFactory.decodeResource(getApplication<Application>().resources, R.drawable.profile_placeholder)
8480
}
8581

8682
override fun onCleared() {
8783
authService.currentUser.removeObserver(userObserver)
8884
}
8985

9086
val onGivenNameChanged: (String) -> Unit = { newValue ->
91-
_givenName.value = newValue
87+
givenName = newValue
9288
}
9389

9490
val onSurnameChanged: (String) -> Unit = { newValue ->
95-
_surname.value = newValue
91+
surname = newValue
9692
}
9793

9894
val onJobTitleChanged: (String) -> Unit = { newValue ->
99-
_jobTitle.value = newValue
95+
jobTitle = newValue
10096
}
10197

10298
val onProfilePicChanged: (Bitmap) -> Unit = { newValue ->
10399
viewModelScope.launch(Dispatchers.Main) {
104-
_profilePic.value = newValue
100+
profilePic = newValue
105101
}
106102
}
107103

108104
val clearToastMessage: () -> Unit = {
109-
_toastMessage.value = ""
105+
toastMessage = ""
110106
}
111107

112108
val onSave: () -> Unit = {
113109
//when saving information to the database need to make sure
114110
//to use Dispatchers.IO so that Disk I/O work isn't done on the main thread
115111
viewModelScope.launch(Dispatchers.IO) {
116112
val profile = HashMap<String, Any>()
117-
profile["givenName"] = givenName.value as Any
118-
profile["surname"] = surname.value as Any
119-
profile["jobTitle"] = jobTitle.value as Any
120-
profile["email"] = emailAddress.value as Any
121-
profile["team"] = team.value as Any
122-
profile["documentType"] = "user" as Any
123-
profilePic.value?.let {
124-
val outputStream = ByteArrayOutputStream()
125-
it.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
126-
profile["imageData"] =
127-
Blob("image/jpeg", outputStream.toByteArray()) as Any
128-
}
113+
profile["givenName"] = givenName
114+
profile["surname"] = surname
115+
profile["jobTitle"] = jobTitle
116+
profile["email"] = emailAddress
117+
profile["team"] = team
118+
profile["documentType"] = "user"
119+
val outputStream = ByteArrayOutputStream()
120+
profilePic.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
121+
profile["imageData"] = Blob("image/jpeg", outputStream.toByteArray())
129122
val didSave = repository.save(profile)
130123

131124
//make sure when we update the UI we update on the Main Thread
132125
withContext(Dispatchers.Main) {
133-
if (didSave) {
134-
_toastMessage.value = "Successfully updated profile"
126+
toastMessage = if (didSave) {
127+
"Successfully updated profile"
135128
} else {
136-
_toastMessage.value = "Error saving, try again later."
129+
"Error saving, try again later."
137130
}
138131
}
139132
}

0 commit comments

Comments
 (0)