Android MVVM添加到收藏夹功能

Android MVVM添加到收藏夹功能,android,kotlin,mvvm,Android,Kotlin,Mvvm,我正在细节屏幕中实现“添加到收藏夹”功能。如果用户点击晶圆厂,我想将晶圆厂设置为选中并更新我的数据库。我如何使用发送到数据库的相同值来在片段中使用(为了保持一致,以防在更新数据库时出现问题) 片段 class BeerDetailsFragment : Fragment(R.layout.fragment_beer_details) { private val viewModel by viewModels<BeerDetailsViewModel>() priv

我正在细节屏幕中实现“添加到收藏夹”功能。如果用户点击晶圆厂,我想将晶圆厂设置为选中并更新我的数据库。我如何使用发送到数据库的相同值来在片段中使用(为了保持一致,以防在更新数据库时出现问题)

片段

class BeerDetailsFragment : Fragment(R.layout.fragment_beer_details) {

    private val viewModel by viewModels<BeerDetailsViewModel>()

    private val args by navArgs<BeerDetailsFragmentArgs>()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        subscribeToObservers()
        viewModel.getBeer(args.beerId)
    }

    private fun subscribeToObservers() {
        viewModel.beer.observe(viewLifecycleOwner, { resource ->
            when(resource.status) {
                Status.SUCCESS -> {
                    loadData(resource.data)
                }
                Status.ERROR -> {
                    showError(resource.message)
                }
                Status.LOADING -> {}
            }
        })
    }
    
    private fun loadData(beerDetails: BeerDomainModel?) {
        if (beerDetails != null) {
            Glide.with(requireContext())
                .load(beerDetails.imageMedium)
                .placeholder(R.drawable.ic_beer)
                .error(R.drawable.ic_beer)
                .fallback(R.drawable.ic_beer)
                .into(beerDetailsImage)

            beerDetailsName.text = beerDetails.name
            beerDetailsDescription.text = beerDetails.description

            fab.isSelected = beerDetails.isFavourite

            fab.setOnClickListener {
                viewModel.updateBeer(beerDetails)
                // I shouldn't do it like this in case there is an issue while updating the DB
                fab.isSelected = !beerDetails.isFavourite
            }
        }
    }
...
类BeerDetailsFragment:Fragment(R.layout.Fragment\u-beer\u-details){
私有val viewModel by viewModels()
私有val args by navArgs()
覆盖已创建的视图(视图:视图,保存状态:捆绑?){
super.onViewCreated(视图,savedInstanceState)
subscribeToObservers()
viewModel.getBeer(args.beerId)
}
私人娱乐订阅betoobserver(){
viewModel.beer.observe(viewLifecycleOwner,{resource->
何时(资源状态){
Status.SUCCESS->{
loadData(resource.data)
}
Status.ERROR->{
淋浴错误(resource.message)
}
Status.LOADING->{}
}
})
}
私人娱乐加载数据(beerDetails:BeerDomainModel?){
if(beerDetails!=null){
Glide.with(requireContext())
.load(beerDetails.imagemedia)
.占位符(R.drawable.ic_beer)
.错误(R.drawable.ic_-beer)
.后备(R.可抽出式ic_啤酒)
.into(beerdeailsimage)
beerDetailsName.text=beerDetails.name
beerDetailsDescription.text=beerDetails.description
fab.isSelected=beerDetails.isfavorite
fab.setOnClickListener{
viewModel.updateBeer(beerDetails)
//我不应该这样做,以防在更新数据库时出现问题
fab.isSelected=!beerDetails.isFavorite
}
}
}
...
查看模型类

class BeerDetailsViewModel @ViewModelInject constructor(private val repository: BreweryRepository) : ViewModel() {

    private val beerId = MutableLiveData<String>()

    fun getBeer(id: String) {
        beerId.value = id
    }

    var beer = beerId.switchMap { id ->
        liveData {
            emit(Resource.loading(null))
            emit(repository.getBeer(id))
        }
    }

    fun updateBeer(beer: BeerDomainModel) {
        viewModelScope.launch {
            repository.updateBeer(beer)
        }
    }
}
类beerdeailsviewmodel@ViewModel注入构造函数(私有val存储库:BreweryRepository):ViewModel(){
private val beerId=MutableLiveData()
趣味啤酒(id:String){
beerId.value=id
}
var beer=beerId.switchMap{id->
实时数据{
发出(资源加载(空))
emit(repository.getBeer(id))
}
}
有趣的更新者(啤酒:BeerDomainModel){
viewModelScope.launch{
repository.updateber(啤酒)
}
}
}
存储库

class BreweryRepository @Inject constructor(private val breweryApi: BreweryApi, private val beerDao: BeerDao, private val responseHandler: ResponseHandler) {

...

    suspend fun getBeer(id: String): Resource<BeerDomainModel> {
        return try {
            withContext(IO) {
                val isInDB = beerDao.isInDB(id)
                if (!isInDB) {
                    val response = breweryApi.getBeer(id).beer.toDomainModel()
                    beerDao.insert(response.toBeerEntity())
                    responseHandler.handleSuccess(response)
                } else {
                    val beer = beerDao.get(id).toDomainModel()
                    responseHandler.handleSuccess(beer)
                }
            }
        } catch (e: Exception) {
            responseHandler.handleException(e)
        }
    }

    suspend fun updateBeer(beer: BeerDomainModel) {
        withContext(IO) {
            val dbBeer = with(beer) {
                copy(isFavourite = !isFavourite)
                toBeerEntity()
            }
            beerDao.update(dbBeer)
        }
    }

}
class BreweryRepository@Inject构造函数(private val breweryApi:breweryApi,private val beerDao:beerDao,private val responseHandler:responseHandler){
...
suspend-fun-getBeer(id:String):资源{
回击{
withContext(IO){
val isInDB=beerDao.isInDB(id)
如果(!isInDB){
val response=breweryApi.getBeer(id.beer.toDomainModel())
insert(response.toBeerEntity())
responseHandler.handleSuccess(响应)
}否则{
val beer=beerDao.get(id).toDomainModel()
负责人,无把手成功(啤酒)
}
}
}捕获(e:例外){
响应句柄异常(e)
}
}
暂停乐趣更新程序(啤酒:BeerDomainModel){
withContext(IO){
val dbBeer=带(啤酒){
复制(IsFavorite=!IsFavorite)
toBeerEntity()
}
beerDao.update(dbBeer)
}
}
}

我更愿意使用具有以下实现的单向流:

不确定DAO是如何实现的,但是如果您使用的是Room,则可以更新get方法,以返回
。这样,无论何时更新数据,您都将返回更新的数据。 然后在虚拟机中,您只需获得
Flow
或数据流并订阅更新。
Flow
有一个非常方便的方法:
asLiveData()
,这样您的代码看起来会更干净


如果你不使用房间,那么我要做的是构造<代码>流>代码>或者某种类型的流,在更新成功的更新中发送新的数据。以前使用过流,我需要先学习如何操作。我可能会使用与get相同的资源模式,或者发送回布尔值,然后根据返回的信息更新VM中的beer。如果您不想进行很多修改,也不介意加载指示器,只需再次调用

getBeer