android Kotlin提高了MutableLiveData Observer的可读性

3yhwsihp  于 2023-06-20  发布在  Android
关注(0)|答案(1)|浏览(192)

我想通过简化MutableLiveData对象的观察者来使我的代码更具可读性。但我不知道该怎么做。我考虑过将每个observe方法的内容移到一个单独的类中,但这只会提高片段的可读性,而新类又会令人困惑。

  1. private fun HomeViewModel.setupObservers() {
  2. messages.observe(viewLifecycleOwner) { response ->
  3. when (response) {
  4. is Resource.Success -> {
  5. response.data?.let { messagesResponse ->
  6. getMessagesWithImageUrl(chatID, messagesResponse)
  7. }
  8. }
  9. is Resource.Error -> {
  10. response.message?.let { message ->
  11. Log.e(TAG, "An error occurred: $message")
  12. }
  13. hideProgressBarLoadMessages()
  14. hideProgressBarSendMessage()
  15. }
  16. is Resource.Loading -> {}
  17. }
  18. }
  19. messagesWithImageUrl.observe(viewLifecycleOwner) {response ->
  20. when(response) {
  21. is Resource.Error -> {
  22. response.message?.let { message ->
  23. Log.e(TAG, "An error occurred: $message")
  24. }
  25. hideProgressBarLoadMessages()
  26. hideProgressBarSendMessage()
  27. }
  28. is Resource.Loading -> {}
  29. is Resource.Success -> {
  30. response.data?.let { messagesResponse ->
  31. adapterMessage
  32. .differ
  33. .submitList(messagesResponse.thread.values.toList())
  34. binding.recyclerViewMessages
  35. .scrollToPosition(adapterMessage.itemCount-1)
  36. hideProgressBarLoadMessages()
  37. hideProgressBarSendMessage()
  38. }
  39. }
  40. }
  41. }
  42. messageMediaUpload.observe(viewLifecycleOwner) { response ->
  43. when(response) {
  44. is Resource.Error -> {
  45. response.message?.let { message ->
  46. Log.e(TAG, "An error occurred: $message")
  47. }
  48. }
  49. is Resource.Loading -> {
  50. showProgressBarSendMessage()
  51. }
  52. is Resource.Success -> {
  53. response.data?.let {
  54. it.metadata?.let { metadata ->
  55. metadata.name?.let { imageName ->
  56. val content = imageName.dropLast(4)
  57. viewModel.sendMessage(
  58. POSTMessage(content, media = true),
  59. POSTLastMessage(content, media = true, msgRead = true),
  60. chatID,
  61. receiverID)
  62. }
  63. }
  64. }
  65. }
  66. }
  67. }
  68. username.observe(viewLifecycleOwner) { response ->
  69. when(response) {
  70. is Resource.Error -> {
  71. response.message?.let { message ->
  72. Log.e(TAG, "An error occurred: $message")
  73. }
  74. }
  75. is Resource.Loading -> { /* TODO: some loading animation */ }
  76. is Resource.Success -> {
  77. response.data?.let { username ->
  78. binding.headlineText.text = username
  79. }
  80. }
  81. }
  82. }
  83. sendMessage.observe(viewLifecycleOwner) { response ->
  84. when(response) {
  85. is Resource.Error -> {
  86. response.message?.let { message ->
  87. Log.e(TAG, "An error occurred: $message")
  88. }
  89. hideProgressBarSendMessage()
  90. }
  91. is Resource.Loading -> {
  92. showProgressBarSendMessage()
  93. }
  94. is Resource.Success -> {}
  95. }
  96. }
  97. setMessageRead.observe(viewLifecycleOwner) { response ->
  98. when(response) {
  99. is Resource.Error -> {
  100. response.message?.let { message ->
  101. Log.e(TAG, "An error occurred: $message")
  102. }
  103. }
  104. is Resource.Loading -> {}
  105. is Resource.Success -> {}
  106. }
  107. }
  108. }

我的资源类看起来像这样:

  1. sealed class Resource<T>(
  2. val data: T? = null,
  3. val message: String? = null) {
  4. class Success<T>(data: T) : Resource<T>(data)
  5. class Error<T>(message: String, data: T? = null) : Resource<T>(data, message)
  6. class Loading<T> : Resource<T>()
  7. }

如果我把它改成这样:

  1. sealed interface Resource<T> {
  2. class Success<T>(val data: T) : Resource<T>
  3. class Error<T>(val message: String) : Resource<T>
  4. class Loading<T> : Resource<T>
  5. }

然后我必须修改ViewModel中的方法,如下所示:

  1. //old Resource
  2. fun getChats() = viewModelScope.launch {
  3. chats.postValue(Resource.Loading())
  4. homeRepository.getChats().collect() {
  5. it.data?.let { getChats ->
  6. setChatIDs(getChats)
  7. getUnreadMessages(getChats)
  8. }
  9. chats.postValue(it)
  10. }
  11. }
  12. //new Resource
  13. private fun getChats() = viewModelScope.launch {
  14. chats.postValue(Resource.Loading())
  15. homeRepository.getChats().collect() {
  16. if(it is Resource.Success) {
  17. val data = (it as Resource.Success).data
  18. setChatIDs(data)
  19. getUnreadMessages(data)
  20. }
  21. chats.postValue(it)
  22. }
  23. }

这将使我的Oberver方法更具可读性,但我不确定这在ViewModel中是否是一个糟糕的做法。

uyhoqukh

uyhoqukh1#

你不能把它们干净地分解成类,因为它使用的是Fragment的内部结构。
但是,通过查看您的代码和所有这些?.let,我认为您需要一个更好的密封类/接口实现。
我猜你的密封类看起来像这样:

  1. sealed class Resource(
  2. val data: String? = null,
  3. val message: String? = null
  4. ) {
  5. object Loading: Resource()
  6. class Success(data: String): Resource(data = data)
  7. class Error(message: String): Resource(message = message)
  8. }

实际上应该是这样的:

  1. sealed interface Resource {
  2. object Loading: Resource
  3. data class Success(val data: String): Resource
  4. data class Error(val message: String): Resource
  5. }

这样,Success类中就不会有无用的message属性,Error类中也不会有无用的data属性。但更重要的是,messagedata不能为空,因为它们不需要为空--它们只在与之相关的类中使用。
那么您就不需要使用所有那些?.let调用,这些调用会使您的代码非常难看。
除此之外,您可以定义:

  1. private fun Resource.Error.log() = Log.e(TAG, "An error occurred: $message")

并使用它来避免代码重复。
when分支中,当只有一个函数调用时,可以将其更改为一行程序,周围没有括号{ }。例如:

  1. when (response) {
  2. // ...
  3. is Resource.Loading -> showProgressBarSendMessage()
  4. //...
  5. }
展开查看全部

相关问题