【问题标题】:Is a good practice to use postDelayed for delay the opening of fragment?使用 postDelayed 延迟打开片段是一个好习惯吗?
【发布时间】:2020-07-14 10:22:37
【问题描述】:

我正在制作一个基于 TMDB 数据库的应用程序。我有一个加载了最新电视节目的 recyclerView。当我点击一张海报时,我会调用 TMDB api,获取一个带有显示信息的对象并打开一个加载了该对象数据的片段。

问题是当我返回并点击其他电视节目时,当片段再次打开时,它会简要显示我点击的上一个电视节目的信息。

我认为问题在于我正在使用 livedata 在 vi​​ewmodel 和片段之间传递数据,并且它正在加载 livedata 中已经存在的数据。 所以我用这个来延迟片段的打开:

HomeFragment - OnCLick

viewmodel.getShowDetails(showId)

val mHandler = Handler()
val monitor = Runnable {
   Navigation.findNavController(view)
             .navigate(HomeFragmentDirections.actionHomeToShowDetail())
}

mHandler.postDelayed(monitor, 300)

视图模型

  private var showMutable = MutableLiveData<ShowDetails>()

    fun getShowData(id: Int) {
        TmdbRepository.getDetails(id) // This returns an RxJava Observable
            .observeOn(Schedulers.io())
            .doOnError(Throwable::printStackTrace)
            .subscribe {
                showMutable.postValue(it)
            }
    }


    fun getShow(): LiveData<ShowDetails> {
        return showMutable
    }

显示DetailFragment

override fun onCreateView(
     viewModel.getShow().observe(viewLifecycleOwner, Observer {
            mShow = it
            setData(mShow) // this fills the textviews, images, etc
     })
}

用这种方法好不好?或者也许我应该使用其他东西在片段和视图模型之间传递数据而不是 livedata?

谢谢。

【问题讨论】:

    标签: java android kotlin mvvm android-livedata


    【解决方案1】:

    很遗憾,使用 postDelayed 不好。

    由于您的 ViewModel 是共享的,因此 MutuableLiveData 将保存之前的电影详细信息的数据。

    解决这个问题可能有两种形式:

    第一种解决方案,使用StateUi,包括LoadingSuccessFailure如下:

    sealed class StateUi {
        data class Success(val data: Any) : StateUi()
        object Loading : StateUi()
        class Error(val throwable: Throwable) : StateUi()
    }
    

    另外,在 doOnSubscribe() 中添加 StateUi.Loading 如下:

    TmdbRepository.getDetails(id) // This returns an RxJava Observable
            .observeOn(Schedulers.io())
            .doOnSubscribe(StateUi.Loading)
            .doOnError(Throwable::printStackTrace)
            .subscribe {
                showMutable.postValue(it)
            }
    

    让你的 MutuableLiveData 如下

    private var showMutable = MutableLiveData<StateUi<ShowDetails>>()
    

    并在您的 Fragment 中观察,这将如何解决您的问题?

    因为你是在观察状态,所以默认情况下 MutuableLiveData 的状态是 Loading,而不是保存上一部电影的数据。

    第二个解决方案, 为每个片段创建单独的 ViewModel 类。但我确实推荐第一种解决方案。

    【讨论】:

    • 是的,但它只是为 API 调用传递一个整数(显示 ID)。但是如果我在打开片段之前拨打电话,我真的不需要它。我可以为 livedata 使用替代方法吗?
    • 我猜你的数据观察可能有问题,你能分享你的片段和viewModel代码吗?
    • 我用一些代码编辑了这个问题,希望有用
    • 你有 HomeFragment 的 viewModel 和 DetailsFragment 的 viewModel 吗?或者它们是共享的?
    • 我已经编辑了我的答案,包括您的问题的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-24
    • 2014-12-22
    • 2020-08-25
    相关资源
    最近更新 更多