簡體   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