Tengo una configuración de repositorio como esta
class ServerTimeRepo @Inject constructor(private val retrofit: Retrofit){ var liveDataTime = MutableLiveData<TimeResponse>() fun getServerTime(): LiveData<TimeResponse> { val serverTimeService:ServerTimeService = retrofit.create(ServerTimeService::class.java) val obs = serverTimeService.getServerTime() obs.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).unsubscribeOn(Schedulers.io()) .subscribe(object : Observer<Response<TimeResponse>> { override fun onComplete() { } override fun onSubscribe(d: Disposable) { } override fun onNext(t: Response<TimeResponse>) { val gson = Gson() val json: String? val code = t.code() val cs = code.toString() if (!cs.equals("200")) { json = t.errorBody()!!.string() val userError = gson.fromJson(json, Error::class.java) } else { liveDataTime.value = t.body() } } override fun onError(e: Throwable) { } }) return liveDataTime } }Entonces tengo un modelo de vista que llama a este repositorio así
class ServerTimeViewModel @Inject constructor(private val serverTimeRepo: ServerTimeRepo):ViewModel() { fun getServerTime(): LiveData<TimeResponse> { return serverTimeRepo.getServerTime() } }Luego tengo una actividad donde tengo un onClickListener donde observo los datos en vivo, como este
tvPWStart.setOnClickListener { val stlv= serverTimeViewModel.getServerTime() stlv.observe(this@HomeScreenActivity, Observer { //this is getting called multiple times?? }) }No sé qué hay de malo en esto. ¿Alguien puede señalarme en la dirección correcta? Gracias.
El problema es que cada vez que se dispara su ClickListener , observa LiveData una y otra vez. Entonces, puedes resolver ese problema siguiendo la siguiente solución:
Tome un objeto MutableLiveData dentro de su ViewModel de forma privada y obsérvelo como LiveData .
class ServerTimeViewModel @Inject constructor(private val serverTimeRepo: ServerTimeRepo):ViewModel() { private val serverTimeData = MutableLiveData<TimeResponse>() // We make private variable so that UI/View can't modify directly fun getServerTime() { serverTimeData.value = serverTimeRepo.getServerTime().value // Rather than returning LiveData, we set value to our local MutableLiveData } fun observeServerTime(): LiveData<TimeResponse> { return serverTimeData //Here we expose our MutableLiveData as LiveData to avoid modification from UI/View } } Ahora, observamos este LiveData directamente fuera de ClickListener y simplemente llamamos al método API desde el botón, como se muestra a continuación:
//Assuming that this code is inside onCreate() of your Activity/Fragment //first we observe our LiveData serverTimeViewModel.observeServerTime().observe(this@HomeScreenActivity, Observer { //In such case, we won't observe multiple LiveData but one }) //Then during our ClickListener, we just do API method call without any callback. tvPWStart.setOnClickListener { serverTimeViewModel.getServerTime() }