【问题标题】:Android Room Database IS updating, but is not sending updates upon returning to a FragmentAndroid Room Database 正在更新,但在返回 Fragment 时未发送更新
【发布时间】:2019-10-02 21:43:15
【问题描述】:

已修复

SEE BELOW

If a picture is worth 1,000 words, a video is worth, like, a lot of words. Here's a video explanation of the issue.

我已经包含了一个视频,因为它使事情变得更加清晰。问题:当我第一次加载包含需要切换状态的项目列表的片段时,我可以很好地切换该状态。我将更新发送到 Room 数据库,然后将更改发送回我的 ViewModel,然后 ViewModel 将它们分派到 Fragment。

但是,当我离开片段并返回时,不再分派更改。我不知道我是在做一些非常愚蠢的事情还是这是一个错误。

如果相关的话,我也在使用 Jetpack 导航组件。我将在下面包含代码。

如果您需要查看下面引用的任何其他代码,请告诉我,我会将其添加到问题中。

非常感谢您的时间和考虑。

显示片段

class ShowsFragment : Fragment(), ShowClickListener, Observer<Resource<List<ShowDomainModel>>> {  

    @Inject  
    lateinit var factory: ViewModelFactory  
    @Inject  
    lateinit var adapter: ShowsAdapter  

    private lateinit var showsViewModel: ShowsViewModel  

    override fun onAttach(context: Context) {  
        super.onAttach(context)  

        AndroidSupportInjection.inject(this)  
        showsViewModel = ViewModelProviders.of(this, factory).get(ShowsViewModel::class.java)  
    }  

    override fun onCreateView(  
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?  
    ) = inflater.inflate(R.layout.fragment_shows, container, false)!!  

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

        adapter.clickListener = this  
        shows.adapter = adapter  
        val shows = showsViewModel.getShows()  
        shows.observe(this, this)  
    }  

    override fun onChanged(resource: Resource<List<ShowDomainModel>>) {  
        Timber.d("onChanged")  
        when (resource.state) {  
            State.SUCCESS -> {  
                adapter.shows = resource.data!!  
                adapter.notifyDataSetChanged()  
            }  
            State.LOADING -> Unit  
            State.ERROR -> TODO("Handle error state in ShowsFragment")  
        }  
    }  

    override fun onShowFavoriteClicked(show: ShowDomainModel) {  

        if (show.favorite) {  
            showsViewModel.unfavoriteShow(show.playlistId)  
        } else {  
            showsViewModel.favoriteShow(show.playlistId)  
        }  
    }  

    override fun onShowClicked(show: ShowDomainModel) {  
        findNavController().navigate(  
            ShowsFragmentDirections.showEpisodes(show.name, show.playlistId)  
        )  
    }  
}

秀道

@Dao  
abstract class ShowsDao {  

    @Query("SELECT * FROM $TABLE_NAME")  
    abstract fun getShows(): Observable<List<ShowCacheModel>>  

    @Insert(onConflict = OnConflictStrategy.IGNORE)  
    abstract fun insertShows(shows: List<ShowCacheModel>)  

    @Query("SELECT * from $TABLE_NAME WHERE favorite = 1")  
    abstract fun getFavoriteShows(): Observable<List<ShowCacheModel>>  

    @Query("UPDATE $TABLE_NAME SET favorite = :favorite WHERE $COLUMN_SHOW_ID = :showId")  
    abstract fun setFavorite(showId: String, favorite: Boolean)  
}

ShowsViewModel

@Singleton  
class ShowsViewModel @Inject constructor(  
    private val getShows: GetShows,  
    private val addShowToFavorites: AddShowToFavorites,  
    private val removeShowFromFavorites: RemoveShowFromFavorites  
) : ViewModel() {  

    private val shows: MutableLiveData<Resource<List<ShowDomainModel>>> = MutableLiveData()  

    init {  
        shows.postValue(Resource.loading())  
        getShows.execute(GetShowsObserver())
    }  

    override fun onCleared() {  
        getShows.dispose()  
        super.onCleared()  
    }  

    fun getShows(): LiveData<Resource<List<ShowDomainModel>>> = shows  

    fun favoriteShow(id: String) = addShowToFavorites.execute(  
        AddShowToFavoritesObserver(),  
        AddShowToFavorites.Params.forShow(id)  
    )  

    fun unfavoriteShow(id: String) = removeShowFromFavorites.execute(  
        RemoveShowFromFavoritesObserver(),  
        RemoveShowFromFavorites.Params.forShow(id)  
    )

    inner class GetShowsObserver : DisposableObserver<List<ShowDomainModel>>() {  
        override fun onComplete() {  
            Log.d("ShowsViewModel","onComplete")  
            throw RuntimeException("GetShows should not complete, should be observing changes to data.")  
        }  

        override fun onNext(showList: List<ShowDomainModel>) {
            shows.postValue(Resource.success(showList))  
        }  

        override fun onError(e: Throwable) {  
            shows.postValue(Resource.error(e.localizedMessage))  
        }  
    }  

    inner class AddShowToFavoritesObserver : DisposableCompletableObserver() {  
        override fun onComplete() = Unit  

        override fun onError(e: Throwable) =  
            shows.postValue(Resource.error(e.localizedMessage))  
    }  

    inner class RemoveShowFromFavoritesObserver : DisposableCompletableObserver() {  
        override fun onComplete() = Unit  

        override fun onError(e: Throwable) =  
            shows.postValue(Resource.error(e.localizedMessage))  
    }  
}

【问题讨论】:

    标签: android android-fragments android-room android-jetpack android-jetpack-navigation


    【解决方案1】:

    原来修复非常简单。我只需要使用 Activity 作为传递给 ViewModel 的生命周期。

    显示片段

    
        // ...
        override fun onAttach(context: Context) {  
            super.onAttach(context)  
    
            AndroidSupportInjection.inject(this)
            // CHANGED ONE LINE AND IT WORKS
            // (changed this to activity!!)  
            // CHANGED ONE LINE AND IT WORKS
            showsViewModel = ViewModelProviders.of(activity!!, factory).get(ShowsViewModel::class.java)  
        } 
        // ...
    
    }
    

    【讨论】:

    • requireActivity() 应该被用来代替活动!!
    • 哎呀!你能解释一下为什么,然后我会进行编辑吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    • 2014-11-10
    • 1970-01-01
    • 2018-05-21
    • 2022-10-18
    • 1970-01-01
    相关资源
    最近更新 更多