1Answer
  • 12
name

A PHP Error was encountered

Severity: Notice

Message: Undefined index: userid

Filename: views/question.php

Line Number: 191

Backtrace:

File: /home/prodcxja/public_html/questions/application/views/question.php
Line: 191
Function: _error_handler

File: /home/prodcxja/public_html/questions/application/controllers/Questions.php
Line: 433
Function: view

File: /home/prodcxja/public_html/questions/index.php
Line: 315
Function: require_once

name Punditsdkoslkdosdkoskdo

Api Call in mvvm Android

i'm new to mvvm and i've been tring to call an api in kotlin in mvvm using retrofit. this is my xml

<TextView
        android:text="TextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textView" app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="84dp" app:layout_constraintTop_toTopOf="parent"/>
<Button
        android:text="Button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button" app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintHorizontal_bias="0.498" app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="332dp" app:layout_constraintTop_toBottomOf="@+id/textView"
        android:layout_marginBottom="8dp" app:layout_constraintBottom_toBottomOf="parent"/>

you can see that i have only two element . one button for calling the API and on to show the result code of the call(whether it is 200 or something else).

class testViewModel: ViewModel() {
    var testInput :MutableLiveData<Int> = MutableLiveData(1)
    var test :LiveData<Int> = testInput
    fun clicked(){


        test = API_Repository.createCode()
        println(test.value.toString())

    }
}

this is my view model.

fun createCode(): LiveData<Int> {
    var sendUser = CreateCodeUserClass()
    sendUser.setUsername("09360767928")
    var data = MutableLiveData<Int>()
    my_API_Interface!!.CreateCode(sendUser).enqueue(object : retrofit2.Callback<Void> {
        override fun onFailure(call: Call<Void>, t: Throwable) {
            data.value = 10000
            println(data.value.toString())
        }

        override fun onResponse(call: Call<Void>, response: Response<Void>) {
            data.value = response.code()

        }

    })
    return data
}

and this is my API call

class MainActivity : AppCompatActivity() {

    public var viewModel = testViewModel()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        viewModel = ViewModelProviders.of(this).get(testViewModel::class.java)
            viewModel.test!!.observe(this, Observer { data ->
                print(data.toString())
                textView.text = data.toString()
            })

        button.setOnClickListener {
            viewModel.clicked()
        }
    }
}

and this is my mainActivity. when i call the api in my view model test is always null where it should be either 10000 or some other number . i think createCode function finishes before OnResponse or OnFailure is triggered. but i don't know what to do and i want to use mvvm.

      • 2
    • have you tried to remove println(test.value.toString()) in your testViewModel class because your CreateCode(sendUser).enqueue is async call it will always make the createCode function finishes before OnResponse or OnFailure is triggered

I guess, your issue is because you observe in activity on one object of LiveData, but when you receive the result from api, you just replace this object with new LiveData. You should to wait result and write it in already created LiveData in your ViewModel. It's possible with MediatorLiveData. Something like this:

val monthData = MediatorLiveData<MonthData>() /// livedata i subscribed in view

This is my "api call" in viewmodel. Here is main magic. I subscribe my viewmodel's livedata to result of my "api call" and pass data from there to this livedata:

fun loadMonthEvents() {
    monthData.addSource(useCase.getCalendarEvents()) {
        monthData.value = it
    }
}

In my case, my repo on RxJava, and i convert it to livedata like this (UseCase):

fun getCalendarEvents(): LiveData<MonthData?> {
    val result = mutableLiveDataOf<MonthData?>()

    appointmentsRepository.getAppointmentsIn().subscribe { data ->
        result.value = data
    }

    return result
}

Hope, it will help you. Anyway, just comment, if you still have questions :)

  • 1
Reply Report