我想通过简化MutableLiveData对象的观察者来使我的代码更具可读性。但我不知道该怎么做。我考虑过将每个observe方法的内容移到一个单独的类中,但这只会提高片段的可读性,而新类又会令人困惑。
private fun HomeViewModel.setupObservers() {
messages.observe(viewLifecycleOwner) { response ->
when (response) {
is Resource.Success -> {
response.data?.let { messagesResponse ->
getMessagesWithImageUrl(chatID, messagesResponse)
}
}
is Resource.Error -> {
response.message?.let { message ->
Log.e(TAG, "An error occurred: $message")
}
hideProgressBarLoadMessages()
hideProgressBarSendMessage()
}
is Resource.Loading -> {}
}
}
messagesWithImageUrl.observe(viewLifecycleOwner) {response ->
when(response) {
is Resource.Error -> {
response.message?.let { message ->
Log.e(TAG, "An error occurred: $message")
}
hideProgressBarLoadMessages()
hideProgressBarSendMessage()
}
is Resource.Loading -> {}
is Resource.Success -> {
response.data?.let { messagesResponse ->
adapterMessage
.differ
.submitList(messagesResponse.thread.values.toList())
binding.recyclerViewMessages
.scrollToPosition(adapterMessage.itemCount-1)
hideProgressBarLoadMessages()
hideProgressBarSendMessage()
}
}
}
}
messageMediaUpload.observe(viewLifecycleOwner) { response ->
when(response) {
is Resource.Error -> {
response.message?.let { message ->
Log.e(TAG, "An error occurred: $message")
}
}
is Resource.Loading -> {
showProgressBarSendMessage()
}
is Resource.Success -> {
response.data?.let {
it.metadata?.let { metadata ->
metadata.name?.let { imageName ->
val content = imageName.dropLast(4)
viewModel.sendMessage(
POSTMessage(content, media = true),
POSTLastMessage(content, media = true, msgRead = true),
chatID,
receiverID)
}
}
}
}
}
}
username.observe(viewLifecycleOwner) { response ->
when(response) {
is Resource.Error -> {
response.message?.let { message ->
Log.e(TAG, "An error occurred: $message")
}
}
is Resource.Loading -> { /* TODO: some loading animation */ }
is Resource.Success -> {
response.data?.let { username ->
binding.headlineText.text = username
}
}
}
}
sendMessage.observe(viewLifecycleOwner) { response ->
when(response) {
is Resource.Error -> {
response.message?.let { message ->
Log.e(TAG, "An error occurred: $message")
}
hideProgressBarSendMessage()
}
is Resource.Loading -> {
showProgressBarSendMessage()
}
is Resource.Success -> {}
}
}
setMessageRead.observe(viewLifecycleOwner) { response ->
when(response) {
is Resource.Error -> {
response.message?.let { message ->
Log.e(TAG, "An error occurred: $message")
}
}
is Resource.Loading -> {}
is Resource.Success -> {}
}
}
}
我的资源类看起来像这样:
sealed class Resource<T>(
val data: T? = null,
val message: String? = null) {
class Success<T>(data: T) : Resource<T>(data)
class Error<T>(message: String, data: T? = null) : Resource<T>(data, message)
class Loading<T> : Resource<T>()
}
如果我把它改成这样:
sealed interface Resource<T> {
class Success<T>(val data: T) : Resource<T>
class Error<T>(val message: String) : Resource<T>
class Loading<T> : Resource<T>
}
然后我必须修改ViewModel中的方法,如下所示:
//old Resource
fun getChats() = viewModelScope.launch {
chats.postValue(Resource.Loading())
homeRepository.getChats().collect() {
it.data?.let { getChats ->
setChatIDs(getChats)
getUnreadMessages(getChats)
}
chats.postValue(it)
}
}
//new Resource
private fun getChats() = viewModelScope.launch {
chats.postValue(Resource.Loading())
homeRepository.getChats().collect() {
if(it is Resource.Success) {
val data = (it as Resource.Success).data
setChatIDs(data)
getUnreadMessages(data)
}
chats.postValue(it)
}
}
这将使我的Oberver方法更具可读性,但我不确定这在ViewModel中是否是一个糟糕的做法。
1条答案
按热度按时间uyhoqukh1#
你不能把它们干净地分解成类,因为它使用的是Fragment的内部结构。
但是,通过查看您的代码和所有这些
?.let
,我认为您需要一个更好的密封类/接口实现。我猜你的密封类看起来像这样:
实际上应该是这样的:
这样,Success类中就不会有无用的
message
属性,Error类中也不会有无用的data
属性。但更重要的是,message
和data
不能为空,因为它们不需要为空--它们只在与之相关的类中使用。那么您就不需要使用所有那些
?.let
调用,这些调用会使您的代码非常难看。除此之外,您可以定义:
并使用它来避免代码重复。
在
when
分支中,当只有一个函数调用时,可以将其更改为一行程序,周围没有括号{ }
。例如: