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
。