如何在android中使用flow和coroutine编辑条目后更新列表?

w46czmvw  于 2023-03-11  发布在  Android
关注(0)|答案(2)|浏览(160)

我有一个简单的存储库SimpleRepository,它使用翻新从服务器获取数据。数据是一个简单的项目列表或一些项目的详细信息。
现在我有一个编辑屏幕,用户可以更改项目名称。所以在用户点击SaveButton后,简单的rest调用被调用,服务器更新项目。
但列表中的项目没有更新。
回购协议如下所示:

interface SimpleRepo {

  fun getAllItems(): Flow<List<Item>>
 
  fun getItem(id: String) : Flow<Item>

  fun updateItemName(id: String, newName: String): Flow<Boolean> //true if server changed the value

  fun updateItemTitle(id: String, newTitle: String): Flow<Boolean> //true if server changed the value

  fun updateItemSubtitle(id: String, newSubtitle: String): Flow<Boolean> //true if server changed the value

  fun updateItemDescription(id: String, newDescription: String): Flow<Boolean> //true if server changed the value
}

repo由用例使用,而用例由视图模型使用。
我的问题是:调用updateItemXxxx()方法后,如何实现SimpleRepo从流中获取新元素?

qhhrdooz

qhhrdooz1#

我找到了一个可行的解决方案。见下文。
关键词是:

  • 使刷新程序全局化
  • 在共享流中将replay设置为1
  • 总是调用tryEmit

因此,短期实施:

private val refresher = MutableSharedFlow<Unit>(replay = 1)

 @OptIn(FlowPreview::class)
 class SimpleRepositoryImpl @Inject constructor(
    private val remote: RemoteDataSource,
 ) : SimpleRepo {

 init {  refresher.tryEmit(Unit) }

 override fun getAllItems(): Flow<List<Item>> = refresher
     .flatMapConcat {
         flow {
            val items = remote
                .getItems()
                 .body()
                 ?.map { Item(it.id, it.name) }
                 ?: emptyList()

             emit(items)
         }
     }

 override fun getItem(id: String) = refresher.flatMapConcat {
     flow {
         val item = remote.getItem(id)
             .body()
             ?.let {
                 Item(it.id, it.name)
             }!!
         emit(item)
     }
 }

 override fun updateItemName(id: String, newName: String): Flow<Boolean> = flow {
     remote.updateName(
         id = id,
         name = newName,
      )
     refresher.tryEmit(Unit)
     emit(true)
  }
}
643ylb08

643ylb082#

你可以试试这样的
onSuccess、更新、API实现不在这里
我建议将所有更新方法更改为suspend,除非您需要获得多个发射

class RepositoryImplementation (private val api:API) : ConversationsRepository{
  val flowOfItems = MutableStateFlow<List<Item>>(emptyList())

  fun getAllItems(): Flow<List<Item>> {
     //you could add also a property in `getAllItems` to do an invalidation or not
     CoroutineScope(Job() + Dispatchers.Default).launch {
            api.getAllItems().onSuccess {
               flowOfItems.update { it }
            }
        }
     return flowOfItems
  }

  suspend fun updateItemName(id: String, newName: String): Boolean {
     apiUpdateItemName(id,newName).onSuccess{
        //depending on your api, if you have the whole list again
        //update the list in `flowOfItems`, or update the list with the change only
     }
  }
}

由于getAllItems()始终返回相同的流,并且您正在向该流写入更新,因此它应该在UI上正确观察元素

相关问题