RxJava Unit test Observable interval, Change response by advancing through time - java

I have a network polling function with Observable interval in my repository
class repository #Inject constructor(
private val api: api,
private val schedulerProvider: SchedulerProvider
) {
private fun networkPoll(): Observable<response> {
return Observable.interval(1L, TimeUnit.Seconds, schedulerProvider.io())
.startWith(0L)
.flatMap {
api.getStatus().subscribeOn(schedulerProvider.io()).toObservable()
}
}
private fun pollStates(): Observable<State> {
return networkPoll()
.map {
// map the response to State1, State2, State3
}
}
fun pollForState3(): Observable<State> {
return pollStates()
.subscribeOn(schedulerProvider.io())
.takeUntil {
it is State3
}
}
}
How do I unit test pollForState3 and change the response by advancing through time?

I solved it by doing this
private lateinit var repository: Repository
private val schedulerProvider = TestSchedulerProvider()
#Mock
private lateinit var api: Api
#Before
fun setup() {
repository = repository(api, schedulerProvider)
}
#Test
fun test() {
`when`(api.getStatus()).thenReturn(
// return such a way that pollStates function map this to State1
)
val testObserver = repository.pollForState3().test()
schedulerProvider.ioScheduler.advanceTimeBy(1L, TimeUnit.MILLISECONDS)
testObserver.assertValue {
it is State1
}
testObserver.assertNotTerminated()
`when`(api.getStatus()).thenReturn(
// now return such a way that pollStates function map this to State3
)
schedulerProvider.ioScheduler.advanceTimeBy(2L, TimeUnit.SECONDS)
testObserver.assertValue {
it is State3
}
testObserver.assertTerminated()
testObserver.dispose()
}
}

Related

How to unit test a callback in parameter - Kotlin

I have a Client class (written in Kotlin in an Android app) that implements an interface ReadyCallback (written in Java in a library of the app, the app is dependent on this library). In Client I have a createClient() method which will create a client with the parameter of ReadyCallback. If it's ready, I will perform other tasks by calling classC.otherMethod(), if not ready, I just create the client without doing other stuff:
In the library:
// Somewhere in this library, I have logic to call `readyCallback.onReady()` when I consider it's "ready"
interface ReadyCallback {
void onReady()
}
class Manager {
private final ReadyCallback readyCallback;
public void onConnected(final boolean isConnected) {
if (isConnected) {
readyCallback.onReady();
}
}
}
In the app:
class ClassA internal constructor(private val clientProvider: ClassB, private val classC: ClassC, private val classD: ClassD) : ReadyCallback {
fun createClient() {
val client = clientProvider.create(getReadyCallback())
}
private fun getReadyCallback() {
return ReadyCallback { onReady() }
}
override fun onReady() {
logInfo { "It's ready! Now do some stuff by calling classC.otherMethod()" }
classC.otherMethod()
}
}
In unit test, I want to verify that when I create the client and it's ready, classC's otherMethod() will be invoked. I tried to do the following but it's not correct:
import com.nhaarman.mockitokotlin2.*
import org.junit.*
class ClassATest {
lateinit var unitUnderTest: ClassA
lateinit var clientProviderMock: ClassB
lateinit var classCMock: ClassC
lateinit var clientMock: ClassD
#Before
override fun setup() {
super.setup()
clientProviderMock = mock()
classCMock = mock()
clientMock = mock()
unitUnderTest = ClassA(clientProvider = clientProviderMock, classC = classCMock, classD = classDMock)
whenever(clientProviderMock.create(any()).thenReturn(client)
}
#Test
fun `when create client then call otherMethod`() {
unitUnderTest.createClient()
verify(classCMock).otherMethod()
}
}
The error message shows:
Wanted but not invoked:
classC.otherMethod();
Actually, there were zero interactions with this mock.
I think the reason I got this error is because, if I don't call getReadyCallback(), it means I am not invoking the callback, so there's no call to classC.otherMethod(). But other than that I am really stuck on this, I don't know how to unit test my desire behavior (If it's ready, classC.otherMethod() will be called, if not ready, this method won't be called).
I know I can't do things like below because unitUnderTest is not a mock object:
callbackMock = mock()
whenever(unitUnderTest.getReadyCallback()).thenReturn(callbackMock)
whenever(clientProviderMock.create(callbackMock).thenReturn(client)
Can anyone help me out please?
The only way I can think of is to add a boolean flag in callback's onReady() method. So it will become:
In library:
interface ReadyCallback {
void onReady(final boolean isReady)
}
class Manager {
private final ReadyCallback readyCallback;
public void onConnected(final boolean isConnected) {
if (isConnected) {
readyCallback.onReady(true);
} else {
readyCallback.onReady(false);
}
}
}
In app:
class ClassA internal constructor(private val clientProvider: ClassB, private val classC: ClassC, private val classD: ClassD) : ReadyCallback {
fun createClient() {
val client = clientProvider.create(getReadyCallback())
}
private fun getReadyCallback() {
return ReadyCallback { isReady -> onReady(isReady) }
}
override fun onReady(isReady: Boolean) {
if (isReady) {
logInfo { "It's ready! Now do some stuff by calling classC.otherMethod()" }
classC.otherMethod()
}
}
}
In unit test:
import com.nhaarman.mockitokotlin2.*
import org.junit.*
class ClassATest {
lateinit var unitUnderTest: ClassA
lateinit var clientProviderMock: ClassB
lateinit var classCMock: ClassC
lateinit var clientMock: ClassD
#Before
override fun setup() {
super.setup()
clientProviderMock = mock()
classCMock = mock()
clientMock = mock()
unitUnderTest = ClassA(clientProvider = clientProviderMock, classC = classCMock, classD = classDMock)
whenever(clientProviderMock.create(any()).thenReturn(client)
}
#Test
fun `when create client and ready then call otherMethod`() {
unitUnderTest.onReady(true)
unitUnderTest.createClient()
verify(classCMock).otherMethod()
}
#Test
fun `when create client and not ready then do not call otherMethod`() {
unitUnderTest.onReady(false)
unitUnderTest.createClient()
verifyZeroInteractions(classCMock)
}
}
But I still don't know how to test without the boolean parameter in the callback's method. Does anyone know how to do that?
I think I figured it out. I don't need a parameter in onReady().
In library:
interface ReadyCallback {
void onReady()
}
// place to determine when is "ready"
class Manager {
private final ReadyCallback readyCallback;
public void onConnected(final boolean isConnected) {
if (isConnected) {
readyCallback.onReady();
}
}
}
In app:
class ClassA internal constructor(private val clientProvider: ClassB, private val classC: ClassC, private val classD: ClassD) : ReadyCallback {
fun createClient() {
val client = clientProvider.create(getReadyCallback())
}
private fun getReadyCallback() {
return ReadyCallback { onReady() }
}
override fun onReady() {
logInfo { "It's ready! Now do some stuff by calling classC.otherMethod()" }
classC.otherMethod()
}
}
In unit test:
import com.nhaarman.mockitokotlin2.*
import org.junit.*
class ClassATest {
lateinit var unitUnderTest: ClassA
lateinit var clientProviderMock: ClassB
lateinit var classCMock: ClassC
lateinit var clientMock: ClassD
#Before
override fun setup() {
super.setup()
clientProviderMock = mock()
classCMock = mock()
clientMock = mock()
unitUnderTest = ClassA(clientProvider = clientProviderMock, classC = classCMock, classD = classDMock)
whenever(clientProviderMock.create(any()).thenReturn(client)
}
#Test
fun `when create client and ready then call otherMethod`() {
unitUnderTest.onReady()
unitUnderTest.createClient()
verify(classCMock).otherMethod()
}
#Test
fun `when create client and not ready then do not call otherMethod`() {
unitUnderTest.createClient()
verifyZeroInteractions(classCMock)
}
}

How to update server response in UI using MVVM pattern

I am using MVVM pattern in my app I have separate repository class for network operations. In repository class I am getting response from the server. How can I show Toast message send from the server in my main activity.
Below is my code:
Repository.java
public class MyRepository {
MutableLiveData<List<Facts>> mutableLiveData = new MutableLiveData<>();
Application application;
public MyRepository(Application application) {
this.application = application;
}
public MutableLiveData<List<Facts>> getMutableLiveData(){
Retrofit retrofit = RetrofitClient.getInstance();
ApiService apiService = retrofit.create(ApiService.class);
apiService.getFacts().subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<List<Facts>>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(List<Facts> facts) {
if(facts.size() > 0 && facts != null){
mutableLiveData.setValue(facts);
}
}
#Override
public void onError(Throwable e) {
TastyToast.makeText(application,e.getMessage(),TastyToast.LENGTH_SHORT,
TastyToast.ERROR).show();
}
#Override
public void onComplete() {
}
});
return mutableLiveData;
}
}
FactsViewModel.java
public class FactsViewModel extends AndroidViewModel {
MyRepository repo;
public FactsViewModel(#NonNull Application application) {
super(application);
repo = new MyRepository(application);
}
public LiveData<List<Facts>> getAllFacts(){
return repo.getMutableLiveData();
}
}
MainActivity.java
private void myFacts(){
FactsViewModel viewModel = new ViewModelProvider(this).get(FactsViewModel.class);
viewModel.getAllFacts().observe(this, new Observer<List<Facts>>() {
#Override
public void onChanged(List<Facts> facts) {
adapter = new FactsAdapter(facts,getActivity());
recycle.setAdapter(adapter);
}
});
}
How can I show error toast messages in MainActivity?
To implement that you firstly need to create a class which has the status of the response ,
Loading which is before the fetching of the data and there you can set progress bar to visible then on success you would set the data to your adapter and right after your hide your progress bar and in the on failure one , you show the toast message error
This is the generic class
class AuthResource<T>(
var authStatus : AuthStatus? = null,
var data : T,
var msg : String? = null
)
fun <T> success(#Nullable data: T): AuthResource<T> {
return AuthResource(
AuthStatus.Success,
data,
null
)
}
fun <T> Error(#NonNull msg: String?, #Nullable data: T) : AuthResource<T>? {
return AuthResource(
AuthStatus.ERROR,
data,
msg
)
}
fun <T> loading(#Nullable data: T): AuthResource<T>? {
return AuthResource(
AuthStatus.LOADING,
data,
null
)
}
enum class AuthStatus {
Success, ERROR, LOADING
}
This is my view model where i implement the authResource with the api response
class MainViewModel #Inject constructor( private var webAuth: WebAuth,
private var favFoodDao: FavFoodDao,
private var application: Application) : ViewModel() {
/// you have to create MediatorLiveData with authresource which contains your modelclass
private var mediatorLiveData = MediatorLiveData<AuthResource<WrapLatestMeals>>()
///Here you return a livedata object
fun ObserverCountries(): LiveData<AuthResource<WrapCountries>> {
var liveData = LiveDataReactiveStreams.fromPublisher(
webAuth.getCountries()
///onerrorreturn , rxjava operator which returns error in case
///of response failure
.onErrorReturn(object : Function<Throwable, WrapCountries> {
override fun apply(t: Throwable): WrapCountries {
var country = WrapCountries()
return country
}
})
.map(object : Function<WrapCountries,
AuthResource<WrapCountries>> {
override fun apply(t: WrapCountries):
AuthResource<WrapCountries> {
if(t.meals.isNullOrEmpty())
{
return Error(
"Error",
t
)!!
}
return success(t)
}
})
.subscribeOn(Schedulers.io())
)
//add that data to mediatorLivedata
mediatorLiveDataCountries.addSource(liveData, Observer {
mediatorLiveDataCountries.postValue(it)
mediatorLiveDataCountries.removeSource(liveData)
})
return mediatorLiveDataCountries
}
This is how you handle the status in your MainActivity
mainViewModel = ViewModelProvider(this,provider)[MainViewModel::class.java]
mainViewModel.ObserverCountries().observe(viewLifecycleOwner, Observer {
when(it.authStatus) {
AuthStatus.LOADING -> /// here you show progressbar in response pre-fetch
{
countriesFragmentBinding.countryprogress.show()
}
AuthStatus.Success -> { // here you update your ui
countriesAdapter = CountriesAdapter(it.data.meals!!,
requireContext())
countriesFragmentBinding.recyclercountries.adapter = countriesAdapter
countriesAdapter!!.deleteCategory(23)
countriesFragmentBinding.countryprogress.hide()
}
AuthStatus.ERROR -> // here you hide your progressbar and show your toast
{
countriesFragmentBinding.countryprogress.hide()
ToastyError(requireContext(),getString(R.string.errorretreivingdata))
}
}
})
return countriesFragmentBinding.root
}
}

A function is not executed in an unit test

I find this hard to explain but will try to keep it as simple as possible
I am writing a unit test in which a function (getQualityControlCheckDataForUplift()) is accessed in another class but it does get into the function and do what it is supposed to, it directly gets to return statement.
This is the function. should I be mocking the QualityControlCheck which is a data class
I have shortened the code to make it a bit clear and easier to follow
In my test case,
I load the MAP - qualityControlChecksDataProvider.loadMapWithQCChecksForMilestone()
Then orderStateMonitor access that map on calling orderStateMonitor.upliftedVolumeUpdated() in test case. which intern accesses getQualityControlCheckDataForUplift() via showQualityControlChecks()
cannot get into getQualityControlCheckDataForUplift() not sure why
any suggestions will be very helpful
I really apologise if the code is not simple to understand
fun getQualityControlCheckDataForUplift(qualityControlMilestone: QualityControlMilestone, uplift: Float):
ArrayList<QualityControlCheck>? {
val qcChecksForUplift: ArrayList<QualityControlCheck>? = ArrayList()
val qcChecksForMilestone = mapOfQCChecksForMilestone[qualityControlMilestone.milestoneText]
qcChecksForMilestone?.forEach {
if (it.uplift == uplift) qcChecksForUplift?.add(it)
}
return qcChecksForUplift
}
My test case
#RunWith(MockitoJUnitRunner::class)
class OrderStateMonitorTest : BaseTest() {
#InjectMocks
private lateinit var orderStateMonitor: OrderStateMonitor
#Mock
private lateinit var qualityControlCheckRequiredDuringFuellingBus: QualityControlCheckRequiredDuringFuellingBus
#Mock
private lateinit var qualityControlChecksDataProvider: QualityControlChecksDataProvider
#Before
fun setUp() {
qualityControlChecksDataProvider = QualityControlChecksDataProvider(offlineDataStorage, app)
}
#Test
fun `upliftedVolumeUpdated abcdefg`() {
qualityControlChecksDataProvider.loadMapWithQCChecksForMilestone()
every(fuelOrderValuesProvider.upliftedVolume()).thenReturn(1000.0f)
orderStateMonitor.upliftedVolumeUpdated()
verify(qualityControlCheckRequiredDuringFuellingBus, never()).postUnavailable()
verify(qualityControlCheckRequiredDuringFuellingBus, once()).postAvailable(qualityControlChecks)
}
}
OrderStateMonitor
class OrderStateMonitor #Inject constructor(
private val orderStorage: CurrentOrderStorage,
private val fuelOrderValuesProvider: FuelOrderValuesProvider,
private val noServiceRequiredAvailabilityBus: NoServiceRequiredAvailabilityBus,
private val qualityControlCheckRequiredDuringFuellingBus: QualityControlCheckRequiredDuringFuellingBus,
private val qualityControlChecksDataProvider: QualityControlChecksDataProvider
) {
fun upliftedVolumeUpdated() {
showQualityControlChecks()
}
private fun showQualityControlChecks() {
// WHEN I TRY TO ACCESS ` //qualityControlChecksDataProvider.getQualityControlCheckDataForUplift` IT DOES NOT GET INTO THAT FUNCTION
val qualityControlChecks =
qualityControlChecksDataProvider.getQualityControlCheckDataForUplift(
QualityControlMilestone.FUELLING, 1000.0f)
}
}
QualityControlChecksDataProvider
class QualityControlChecksDataProvider #Inject constructor(
private val offlineDataStorage: OfflineDataStorage,
private val app: App
) {
private val mapOfQCChecksForMilestone = LinkedHashMap<String, ArrayList<QualityControlCheck>?>()
fun loadMapWithQCChecksForMilestone() {
QualityControlMilestone.values().forEach {
mapOfQCChecksForMilestone.put(it.milestoneText, getQualityControlCheckDataForMilestone(it))
}
}
fun getQualityControlCheckData(qualityControlMilestone: QualityControlMilestone):
ArrayList<QualityControlCheck>? =
mapOfQCChecksForMilestone[qualityControlMilestone.milestoneText]
fun getQualityControlCheckDataForUplift(qualityControlMilestone: QualityControlMilestone, uplift: Float):
ArrayList<QualityControlCheck>? {
//DOES NOT GET INTO THIS FUNCTION I RUN THE TEST CASE
val qcChecksForUplift: ArrayList<QualityControlCheck>? = ArrayList()
val qcChecksForMilestone = mapOfQCChecksForMilestone[qualityControlMilestone.milestoneText]
qcChecksForMilestone?.forEach {
if (it.uplift == uplift) qcChecksForUplift?.add(it)
}
return qcChecksForUplift
}
//THERE ARE OTHER PRIVATE FUNCTION WHICH THE ABOVE CODE WILL ACCESS WHICH WORK FINE
}
The method not executed because you mocked the class
#RunWith(MockitoJUnitRunner::class)
class OrderStateMonitorTest : BaseTest() {
#InjectMocks
private lateinit var orderStateMonitor: OrderStateMonitor
#Mock
private lateinit var qualityControlCheckRequiredDuringFuellingBus: QualityControlCheckRequiredDuringFuellingBus
private lateinit var qualityControlChecksDataProvider: QualityControlChecksDataProvider
#Before
fun setUp() {
qualityControlChecksDataProvider = spy(QualityControlChecksDataProvider(offlineDataStorage, app))
}
#Test
fun `upliftedVolumeUpdated abcdefg`() {
qualityControlChecksDataProvider.loadMapWithQCChecksForMilestone()
every(fuelOrderValuesProvider.upliftedVolume()).thenReturn(1000.0f)
orderStateMonitor.upliftedVolumeUpdated()
verify(qualityControlCheckRequiredDuringFuellingBus, never()).postUnavailable()
verify(qualityControlCheckRequiredDuringFuellingBus, once()).postAvailable(qualityControlChecks)
}
}
or use CALL_REAL_METHOD
#RunWith(MockitoJUnitRunner::class)
class OrderStateMonitorTest : BaseTest() {
#InjectMocks
private lateinit var orderStateMonitor: OrderStateMonitor
#Mock
private lateinit var qualityControlCheckRequiredDuringFuellingBus: QualityControlCheckRequiredDuringFuellingBus
private lateinit var qualityControlChecksDataProvider: QualityControlChecksDataProvider
// java syntax
#before
public void setUp(){
qualityControlChecksDataProvider = mock(QualityControlChecksDataProvider, Mocktio.CALL_REAL_METHOD);
}
#Test
fun `upliftedVolumeUpdated abcdefg`() {
qualityControlChecksDataProvider.loadMapWithQCChecksForMilestone()
every(fuelOrderValuesProvider.upliftedVolume()).thenReturn(1000.0f)
orderStateMonitor.upliftedVolumeUpdated()
verify(qualityControlCheckRequiredDuringFuellingBus, never()).postUnavailable()
verify(qualityControlCheckRequiredDuringFuellingBus, once()).postAvailable(qualityControlChecks)
}
}

LivePagedList emitting empty list

I am using a paging library from Android Architecture Components.
Paging is implemented using ItemKeyedDataSource
class MyDatasource(
private val queryMap: HashMap<String, String>) : ItemKeyedDataSource<String, Order>() {
private val compositeDisposable: CompositeDisposable by lazy { CompositeDisposable() }
override fun loadInitial(params: LoadInitialParams<String>, callback: LoadInitialCallback<Order>) {
compositeDisposable.add(
MyService.getService().fetchData(queryMap)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(object : DisposableObserver<OrdersResponse>() {
override fun onNext(orders: OrdersResponse) {
callback.onResult(orders.data)
}
override fun onError(e: Throwable) {
e.printStackTrace()
}
override fun onComplete() {
}
})
)
}
override fun loadBefore(params: LoadParams<String>, callback: LoadCallback<Order>) {
// do nothing
}
override fun loadAfter(params: LoadParams<String>, callback: LoadCallback<Order>) {
queryMap["offsetOrderId"] = params.key
compositeDisposable.add(
MyService.getService().fetchData(queryMap)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(object : DisposableObserver<OrdersResponse>() {
override fun onNext(orders: OrdersResponse) {
callback.onResult(orders.data)
}
override fun onError(e: Throwable) {
}
override fun onComplete() {
}
})
)
}
override fun getKey(item: Order): String {
return item.orderId
}
}
I build pagedlist in my viewmodel
class MyViewModel() : ViewModel() {
private var myPagingConfig: PagedList.Config? = null
var dataList: LiveData<PagedList<Order>>? = null
fun getOrders(params: HashMap<String, String>) {
if (myPagingConfig == null) {
myPagingConfig = PagedList.Config.Builder()
.setPageSize(LIMIT)
.setPrefetchDistance(10)
.setEnablePlaceholders(false)
.build()
}
dataList = LivePagedListBuilder(MyDataFactory(
MyDatasource(params)), myPagingConfig!!)
.setInitialLoadKey(null)
.setFetchExecutor(Executors.newFixedThreadPool(5))
.build()
}
}
However, when I observe the dataList in my activity, it sometimes (most of the times) returns an empty list, while in logcat I see that I had fetched data successfully. callback.onResult is invoked after it returns an empty list, but observer never gets notified again.
Can you tell me if what would cause this?

Android get LiveData from Retrofit call

I'm trying to fetch some data with Retrofit on my Android project update this on the ViewModel and my activity with LiveData.
Here is my service Class:
class PaymentService {
private var paymentMethodList = ArrayList<PaymentMethodModel>()
private val paymentMethodListLiveData = MutableLiveData<List<PaymentMethodModel>>()
init {
paymentMethodListLiveData.value = paymentMethodList
}
fun fetchPaymentMethods() {
val retrofit = Retrofit.Builder()
.baseUrl(SERVICE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
val service = retrofit.create(PaymentClient::class.java)
val jsonCall = service.getListOfPaymentMethods()
jsonCall.enqueue(object : Callback<List<PaymentMethodModel>> {
override fun onResponse(call: Call<List<PaymentMethodModel>>, response: Response<List<PaymentMethodModel>>) {
paymentMethodList = (response.body() as ArrayList<PaymentMethodModel>?)!!
}
override fun onFailure(call: Call<List<PaymentMethodModel>>, t: Throwable) {
//TODO
}
})
}
And here is where I'm trying to listen to the changes on the list:
goToNextButton.setOnClickListener {
paymentMethods = PaymentMethodSelectionViewModel().getAllPaymentMethods()
paymentMethods!!.observe(viewLifecycleOwner, Observer {
Log.e("", "")
})
}
The problem is that so far I'm getting the list only the first time with 0 elements and this observer method is not getting called after the rest call is made and the list updated.
Edit
class PaymentRepository {
private val paymentService = PaymentService()
fun getPaymentMethods(): LiveData<List<PaymentMethodModel>> {
paymentService.fetchPaymentMethods()
return paymentService.getPaymentMethods()
}
}
class PaymentMethodSelectionViewModel: ViewModel() {
private val paymentRepository = PaymentRepository()
private val paymentMethods = paymentRepository.getPaymentMethods()
fun getAllPaymentMethods(): LiveData<List<PaymentMethodModel>> {
paymentRepository.getPaymentMethods()
return paymentMethods
}
}
Change your request into viewmodel
class PaymentMethodSelectionViewModel: ViewModel() {
//Data
var paymentMethodList = MutableLiveData<List<PaymentMethodModel>>()
fun getAllPayments(){
val retrofit = Retrofit.Builder()
.baseUrl(SERVICE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
val service = retrofit.create(PaymentClient::class.java)
val jsonCall = service.getListOfPaymentMethods()
jsonCall.enqueue(object : Callback<List<PaymentMethodModel>> {
override fun onResponse(call: Call<List<PaymentMethodModel>>, response: Response<List<PaymentMethodModel>>) {
var data: List<PaymentMethodModel> = (response.body() as ArrayList<PaymentMethodModel>?)!!
paymentMethodList.value=data
}
override fun onFailure(call: Call<List<PaymentMethodModel>>, t: Throwable) {
//TODO
}
})
}
}
in your view (activity) use
//load
paymentMethodSelectionViewModel.getAllPayments();
//Observers
paymentMethodSelectionViewModel.paymentMethodList.observe(this,
Observer { list ->
// your code
})
I recommend you use retrofit 2 with corutines or RXJAVA2,
check this tutorial
https://medium.com/#amtechnovation/android-architecture-component-mvvm-part-1-a2e7cff07a76
https://medium.com/#saquib3705/consuming-rest-api-using-retrofit-library-with-the-help-of-mvvm-dagger-livedata-and-rxjava2-in-67aebefe031d
As #tyczj says in the comment, every time you use a LiveData, you have to decide when all the observers receive an update notification.
You can do this notification by calling post function of your paymentMethodListLiveData object. This is the correct way to use LiveData in Java.
In Kotlin I think you have to add something like this on your onResponse method:
paymentMethodListLiveData.value = paymentMethodList;
to implicitly call the post method and trigger methods in your observe function.
Hope this help or give you some hints.
Cheers

Categories