繁体   English   中英

分段。 getViewLifeCycleOwner 不会阻止多次调用 LiveData Observer

[英]Fragment. getViewLifeCycleOwner doesn't prevent multiple calls of LiveData Observer

我使用 Clean Architecture、LiveData、Navigation 组件和底部导航视图。
我正在创建一个带有三个选项卡的简单应用程序。 默认情况下,第一个选项卡 Fragment 使用某些 API 加载用户数据。 当我转到另一个选项卡然后返回到第一个选项卡片段时,我看到, observe返回一个新数据!

当我切换回第一个选项卡时,我需要observe不要再次返回数据! 我究竟做错了什么? 请问你能帮帮我吗?

Ps 对于导航,我使用来自navigation-advanced-sample 的示例,并且在切换选项卡后没有调用onDestroy

Observe LiveData from ViewModel in Fragment一文中的第一个解决方案说:

一种适当的解决方案是使用 getViewLifeCycleOwner() 作为 LifeCycleOwer,同时观察 onActivityCreated 中的 LiveData,如下所示。

我使用以下代码,但它对我不起作用:

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    Timber.d("onActivityCreated")
    viewModel.getProfileLive().observe(viewLifecycleOwner, observer)
}

文章架构组件陷阱 - 第 1 部分中的第二个解决方案建议使用重置现有观察者在 onDestroyView() 中手动取消订阅观察者 但它对我也不起作用......

ProfileFragment.kt

class ProfileFragment : DaggerFragment() {

    @Inject
    lateinit var viewModel: ProfileFragmentViewModel

    private val observer = Observer<Resource<Profile>> {
        when (it.status) {
            Resource.Status.LOADING -> {
                Timber.i("Loading...")
            }
            Resource.Status.SUCCESS -> {
                Timber.i("Success: %s", it.data)
            }
            Resource.Status.ERROR -> {
                Timber.i("Error: %s", it.message)
            }
        }
    };

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Timber.d("onCreate")
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        Timber.d("onCreateView")
        return inflater.inflate(R.layout.fragment_profile, container, false)
    }

    fun <T> LiveData<T>.reObserve(owner: LifecycleOwner, observer: Observer<T>) {
        removeObserver(observer)
        observe(owner, observer)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        Timber.d("onViewCreated")
        viewModel.getProfileLive().observe(viewLifecycleOwner, observer)
        // viewModel.getProfileLive().reObserve(viewLifecycleOwner, observer)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        Timber.d("onActivityCreated")
    }

    override fun onDestroyView() {
        super.onDestroyView()
        Timber.d("onDestroyView")
        // viewModel.getProfileLive().removeObserver(observer)
    }

    override fun onDestroy() {
        super.onDestroy()
        Timber.d("onDestroy")
    }

    override fun onDetach() {
        super.onDetach()
        Timber.d("onDetach")
    }
}

ProfileFragmentViewModel.kt

class ProfileFragmentViewModel @Inject constructor(
    private val profileUseCase: ProfileUseCase
) : ViewModel() {

    init {
        Timber.d("Init profile VM")
    }

    fun getProfileLive() = profileUseCase.getProfile()
}

配置文件用例

class ProfileUseCase @Inject constructor(
    private val profileRepository: ProfileRepository
) {

    fun getProfile(): LiveData<Resource<Profile>> {
        return profileRepository.getProfile()
    }
}

ProfileRepository.kt class ProfileRepository @Inject 构造函数(私有 val loginUserDao:LoginUserDao,私有 val profileDao:ProfileDao,){

fun getProfile(): LiveData<Resource<Profile>> =
    liveData(Dispatchers.IO)
    {
        emit(Resource.loading(data = null))

        val profile = profileDao.getProfile()

        // Emit Success result...
    }

}

这是因为Fragment Lifecycle 的工作方式。 当您从片段来回移动时,将再次调用onViewCreated() onViewCreated您正在调用viewModel.getProfileLive() ,它从存储库返回实时数据并观察它。

由于每次移回FragmentonViewCreated()都会被调用,因此您对viewModel.getProfileLive()调用viewModel.getProfileLive()被调用,然后再次调用存储库,这再次触发了 Fragment 中的observe方法。

为了解决这个问题,在你的ViewModel 中创建一个LiveData变量,将它设置为从Repository返回的Live Data Fragment 中观察ViewModelLiveData 变量,而不是从Repository返回的变量 这样,您的observe方法将在第一次并且仅在您的存储库中的数据发生变化时触发。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM