Last active
October 22, 2020 22:38
-
-
Save dleonett/de93a014af777963bcf64e4aac8c0340 to your computer and use it in GitHub Desktop.
Single View State LiveData example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.leonett.photofeed.ui.feature.account | |
import android.content.Context | |
import android.content.Intent | |
import android.view.View | |
import androidx.lifecycle.Observer | |
import androidx.lifecycle.ViewModelProvider | |
import androidx.navigation.fragment.findNavController | |
import com.bumptech.glide.Glide | |
import com.bumptech.glide.request.RequestOptions | |
import com.leonett.photofeed.App | |
import com.leonett.photofeed.R | |
import com.leonett.photofeed.ui.base.BaseFragment | |
import com.leonett.photofeed.ui.feature.login.LoginActivity | |
import kotlinx.android.synthetic.main.fragment_account.* | |
import javax.inject.Inject | |
class AccountFragment : BaseFragment() { | |
@Inject | |
lateinit var accountViewModelFactory: AccountViewModelFactory | |
private lateinit var accountViewModel: AccountViewModel | |
override val layoutId: Int | |
get() = R.layout.fragment_account | |
override fun onAttach(context: Context) { | |
super.onAttach(context) | |
(requireContext().applicationContext as App).appComponent.accountComponent().create() | |
.inject(this) | |
} | |
override fun initVars() { | |
accountViewModel = ViewModelProvider(this, accountViewModelFactory) | |
.get(AccountViewModel::class.java) | |
} | |
override fun initViews(view: View) { | |
btnOpenAbout.setOnClickListener { navigateToAbout() } | |
btnSignOut.setOnClickListener { logoutUser() } | |
} | |
override fun observeViewModels() { | |
observeSingleStateLiveData() | |
observeMultipleLiveData() | |
} | |
private fun observeSingleStateLiveData() { | |
// Screen state | |
accountViewModel.screenStateLiveData.observe(viewLifecycleOwner, Observer { | |
when (it) { | |
// Loading state | |
is AccountScreenState.Loading -> { | |
showProgressDialog("Loading...") | |
} | |
// Success state | |
is AccountScreenState.Success -> { | |
hideProgressDialog() | |
Glide.with(requireContext()) | |
.load(it.userInfo.avatarUrl) | |
.apply(RequestOptions().circleCrop()) | |
.apply(RequestOptions().placeholder(R.drawable.placeholder_image_circle)) | |
.into(imgAvatar) | |
txtName.text = it.userInfo.name | |
txtCity.text = it.userInfo.city | |
btnFriends.text = String.format("Friends (%d)", it.friendsInfo.count) | |
btnFriends.visibility = View.VISIBLE | |
btnPhotos.text = String.format("Photos (%d)", it.photosInfo.count) | |
btnPhotos.visibility = View.VISIBLE | |
} | |
// Error state | |
is AccountScreenState.Error -> { | |
hideProgressDialog() | |
showPersistentSnackbar(txtName, it.message, "Dismiss") { | |
// Just dismiss snack bar | |
} | |
} | |
} | |
}) | |
} | |
private fun observeMultipleLiveData() { | |
// Loader | |
accountViewModel.loaderLiveData.observe(viewLifecycleOwner, Observer { | |
if (it) { | |
showProgressDialog("Loading...") | |
} else { | |
hideProgressDialog() | |
} | |
}) | |
// User info | |
accountViewModel.userInfoLiveData.observe(viewLifecycleOwner, Observer { | |
Glide.with(requireContext()) | |
.load(it.avatarUrl) | |
.apply(RequestOptions().circleCrop()) | |
.apply(RequestOptions().placeholder(R.drawable.placeholder_image_circle)) | |
.into(imgAvatar) | |
txtName.text = it.name | |
txtCity.text = it.city | |
}) | |
// Friends info | |
accountViewModel.friendsInfoLiveData.observe(viewLifecycleOwner, Observer { | |
btnFriends.text = String.format("Friends (%d)", it.count) | |
btnFriends.visibility = View.VISIBLE | |
}) | |
// Photos info | |
accountViewModel.photosInfoLiveData.observe(viewLifecycleOwner, Observer { | |
btnPhotos.text = String.format("Photos (%d)", it.count) | |
btnPhotos.visibility = View.VISIBLE | |
}) | |
// Error banner | |
accountViewModel.errorLiveData.observe(viewLifecycleOwner, Observer { | |
showPersistentSnackbar(txtName, it, "Dismiss") { | |
// Just dismiss snack bar | |
} | |
}) | |
} | |
private fun navigateToAbout() { | |
findNavController().navigate(R.id.actionAbout) | |
} | |
private fun logoutUser() { | |
accountViewModel.logoutUser() | |
navigateToLogin() | |
} | |
private fun navigateToLogin() { | |
val intent = Intent(requireActivity(), LoginActivity::class.java) | |
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK | |
startActivity(intent) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.leonett.photofeed.ui.feature.account | |
import androidx.lifecycle.LiveData | |
import androidx.lifecycle.MutableLiveData | |
import androidx.lifecycle.ViewModel | |
import androidx.lifecycle.viewModelScope | |
import com.leonett.photofeed.data.UserRepository | |
import kotlinx.coroutines.delay | |
import kotlinx.coroutines.launch | |
import javax.inject.Inject | |
class AccountViewModel @Inject constructor(private val userRepository: UserRepository) : | |
ViewModel() { | |
private var _userInfoLiveData: MutableLiveData<UserInfo> = MutableLiveData() | |
val userInfoLiveData: LiveData<UserInfo> | |
get() = _userInfoLiveData | |
private var _friendsInfoLiveData: MutableLiveData<FriendsInfo> = MutableLiveData() | |
val friendsInfoLiveData: LiveData<FriendsInfo> | |
get() = _friendsInfoLiveData | |
private var _photosInfoLiveData: MutableLiveData<PhotosInfo> = MutableLiveData() | |
val photosInfoLiveData: LiveData<PhotosInfo> | |
get() = _photosInfoLiveData | |
private var _errorLiveData: MutableLiveData<String> = MutableLiveData() | |
val errorLiveData: LiveData<String> | |
get() = _errorLiveData | |
private var _loaderLiveData: MutableLiveData<Boolean> = MutableLiveData() | |
val loaderLiveData: LiveData<Boolean> | |
get() = _loaderLiveData | |
private var _screenStateLiveData: MutableLiveData<AccountScreenState> = MutableLiveData() | |
val screenStateLiveData: LiveData<AccountScreenState> | |
get() = _screenStateLiveData | |
init { | |
viewModelScope.launch { | |
//successMultipleLiveData() | |
//errorMultipleLiveData() | |
successSingleViewState() | |
//errorSingleViewState() | |
} | |
} | |
private suspend fun successSingleViewState() { | |
_screenStateLiveData.value = AccountScreenState.Loading | |
delay(2000) | |
_screenStateLiveData.value = AccountScreenState.Success( | |
UserInfo( | |
"John Smith", | |
"New York", | |
"https://cactusthemes.com/blog/wp-content/uploads/2018/01/tt_avatar_small.jpg" | |
), | |
FriendsInfo(200), | |
PhotosInfo(90) | |
) | |
} | |
private suspend fun errorSingleViewState() { | |
_screenStateLiveData.value = AccountScreenState.Loading | |
delay(2000) | |
_screenStateLiveData.value = AccountScreenState.Error("User does not exist") | |
} | |
private suspend fun successMultipleLiveData() { | |
_loaderLiveData.value = true | |
delay(2000) | |
_loaderLiveData.value = false | |
_userInfoLiveData.value = | |
UserInfo( | |
"John Smith", | |
"New York", | |
"https://cactusthemes.com/blog/wp-content/uploads/2018/01/tt_avatar_small.jpg" | |
) | |
_friendsInfoLiveData.value = FriendsInfo(200) | |
_photosInfoLiveData.value = PhotosInfo(90) | |
} | |
private suspend fun errorMultipleLiveData() { | |
_loaderLiveData.value = true | |
delay(2000) | |
_loaderLiveData.value = false | |
_errorLiveData.value = "User does not exist" | |
} | |
fun logoutUser() { | |
userRepository.clearLocalUser() | |
} | |
} | |
data class UserInfo(val name: String, val city: String, val avatarUrl: String) | |
data class PhotosInfo(val count: Int) | |
data class FriendsInfo(val count: Int) | |
sealed class AccountScreenState { | |
object Loading : AccountScreenState() | |
data class Success( | |
val userInfo: UserInfo, | |
val friendsInfo: FriendsInfo, | |
val photosInfo: PhotosInfo | |
) : AccountScreenState() | |
data class Error(val message: String) : AccountScreenState() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment