簡體   English   中英

LiveData 觀察器未被刪除

[英]LiveData observer is not removed

我正在嘗試在ViewModel中獲取LiveData更新,並確保觀察者沒有泄漏,但它正在泄漏。 典型的問題是觀察者沒有存儲在變量中,但這里不是這種情況; lambda 存儲在一個變量中。

    private val observer: (List<MusicFile>) -> Unit =
        { musicFiles: List<MusicFile> ->
            _uiState.postValue(FragmentMusicListState(musicFiles))
        }

    init {
        musicRepository.musicFiles.observeForever(observer)
    }

    @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
    public override fun onCleared() {
        super.onCleared()
        musicRepository.musicFiles.removeObserver(observer)
    }

問題是在調用 onCleared 之后,觀察者仍然依附。 我通過以下測試驗證了這一點。

    @Test
    fun onCleared_RemovesObserver() {
        val musicRepository = MusicRepository.getInstance()
        val context = InstrumentationRegistry.getInstrumentation().targetContext
        musicRepository.loadMusicFiles(context.contentResolver)
        val musicFiles = musicRepository.musicFiles
        val viewModel = FragmentMusicListViewModel(SavedStateHandle(), musicRepository)

        viewModel.onCleared()
        assert(!musicFiles.hasObservers())
    }

另外,我已經調試了最后一行的測試,musicFile 的屬性顯示觀察者仍然是附加的。 屬性 mActiveCount 和 mObservers 顯示觀察者仍然依附,

我如何真正刪除觀察者?

LiveData 在 observeForever 和 removeObserver 中接受類型為Observer<T>的參數。 Observer是Kotlin認為Java寫在androidx.lifecycle庫中的一個函數式接口

您傳入的是(List<MusicFile>) -> Unit類型。

這是一個高階 function 並且與Observer<List<MusicFile>>不是同一類型。 它們在功能上相似,因為它們都有一個類型為List<MusicFile>的參數並且都返回Unit ,所以 Kotlin 的作用是好是壞(在這種情況下更糟)是它會為你“轉換”類型.

當 Kotlin 從高階 function“轉換”到功能接口時,它正在創建一個新的 object。當調用 observeForever 或 removeObserver 時,代碼中每次都會發生這種情況。 這就是 removeObserver 不起作用的原因,因為無論代碼看起來如何,您實際上並沒有傳遞相同的 object 。 我以前寫過這個。

簡而言之,您可以通過將觀察者的類型更改為觀察者來解決您的問題:

private val observer: Observer<List<MusicFile>> =
    Observer { musicFiles: List<MusicFile> ->
        // _uiState.postValue(FragmentMusicListState(musicFiles))
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM