Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

have a class implement multiple Observer

I implemented a Fragment that initially implemented android.arch.lifecycle.Observer and I wanted to start observing some other live data but can't. I started with this:

class MyFragment : BaseFragment(), Observer<FragmentData> {
  lateinit var viewModel: MyViewModel

  override fun onActivityCreated(savedInstanceState: Bundle?) {
    viewModel.fragmentData.observe(this, this)
  }

  override fun onChanged(data: FragmentData?) {
    activity?.title = getTitleFromData(data)
  }
}

If I update the class to include the other observable data like this:

class MyFragment : BaseFragment(), Observer<FragmentData>, Observer<OtherData> {
  lateinit var viewModel: MyViewModel

  override fun onActivityCreated(savedInstanceState: Bundle?) {
    viewModel.fragmentData.observe(this, this)
  }

  override fun onChanged(otherData: OtherData) {
    // update UI from otherData
  }

  override fun onChanged(data: FragmentData?) {
    activity?.title = getTitleFromData(data)
  }
}

I get an error:

Type parameter T of 'Observer' has inconsistent values: FragmentData, OtherData A supertype appears twice

I would like some help understanding why the compiler isn't able to discern the difference between the types and wondered the best alternative pattern.

something like this?:

viewModel.fragmentData.observe(this, fragmentDataObserver)

private val fragmentDataObserver = Observer<Fragmentdata> {
   activity?.title = getTitleFromData(it)
}
like image 216
Jeff Avatar asked Jun 25 '26 19:06

Jeff


1 Answers

You can try yo implement a generic Observer interface like this:

class MyFragment : BaseFragment(), Observer<Any> {...} 

and then on the onChanged method use

override fun onChanged(any: Any?) {
    when:
    any is isOtherData -> Do OtherData things
    any is FragmentData -> Do FragmentData things
}

A second workaround is to make a father class of the OtherData and FragmentData, FatherInterface is just an interface with nothing in the body:

interface OtherData: FatherInterface{}...
interface FragmentData : FatherInterface{}...

Then you can do

class MyFragment : BaseFragment(), Observer<FatherInterface>{}...

override fun onChanged(fatherInterface: FatherInterface?) {
    when{
        fatherInterface is OtherData -> ...
        fatherInterface is FragmentData -> ...
    }
    // update UI from otherData
}
like image 184
Erick Avatar answered Jun 28 '26 12:06

Erick



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!