1

In this case, I have two fragments in BottomNavigationView: Home and Dictionary.

Inside of DictionaryFragment I show BottomSheetFragment with EditText and Button. When the user clicks to the button, the following code executing:

if (name.isNotEmpty()) {
    sharedViewModel.setNewPackName(name)
}

where name is text from EditText and SharedViewModel:

val currentPackName = MutableLiveData<String>()

fun setNewPackName(packName: String) {
    currentPackName.postValue(packName)
}

Inside of DictionaryFragment I have this code:

override fun setObservers() {
    sharedViewModel.currentPackName.observe { newPackName ->
        Timber.tag("newName").d("setObservers(): $newPackName")
        pack_name.text = newPackName
    }
}

But when I moving DictionaryFragment -> HomeFragment -> DictionaryFragment, I see duplicate of "setObservers(): $newPackName" string in my Logcat. Repeating these steps (D-> H-> D) I see the same situation: the next line is printed

BaseViewModel

open class BaseViewModel : ViewModel() {

   val compositeDisposable by lazy { CompositeDisposable() }

    protected fun <T : Any> Observable<T>.compositeSubscribe(
        onNext: (T) -> Unit = {},
        onError: (Throwable) -> Unit = {},
        onComplete: () -> Unit = {}
    ) = composite(
        subscribe(onNext, onError, incomplete)
    )

    private fun composite(disposable: Disposable) {
        compositeDisposable.add(disposable)
    }

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

To be honest, I don’t know what could be the problem. I also use Navigation architecture Component where the visual state of the fragments is preserved, but the life cycle methods are called again.

EDIT: This problem occurs if I have viewModel.smth.observe() and when I switch between fragments (for example, D -> H -> D)

EDIT_2: In my BaseFragment I have the following extension function:

protected inline fun <T> LiveData<T>.observe(crossinline codeBlock: (T) -> Unit) {
    observe(this@BaseFragment, Observer { it -> it?.let { codeBlock(it) } })
}

I've tried to change it to:

protected inline fun <T> LiveData<T>.observe(crossinline codeBlock: (T) -> Unit) {
    val observer = Observer<T> { it -> it?.let { codeBlock(it) } }
    removeObserver(observer)
    observe(this@BaseFragment, observer)
}

but the problem is still here.

Please, help me to solve this problem.

  • Where is the setObservers() method defined and where and when is it invoked? – Ridcully May 02 '20 at 04:20
  • @ADM, trying to figure out –  May 02 '20 at 04:33
  • @Ridcully, it's open fun defined in BaseFragment and invoked in onViewCreated() –  May 02 '20 at 04:34
  • edited my question with **EDIT_2** –  May 02 '20 at 04:56
  • @ADM, thank you, it works fine with the third method in this article. But can I somehow do this with inline function? It’s not very nice to create a separate object each time –  May 02 '20 at 05:14

0 Answers0