Home > other >  Can't log any data from API call
Can't log any data from API call

Time:07-12

I'm pretty new to kotlin, and I feel pretty much overwhelmed by it. I'd like to ask - how I can display any data from MutableLiveData? I've tried to Log it, but it doesn't seem to work. I've already added the internet permission to the manifest. Here's the code:

ApiServices

interface ApiServices {
@GET("/fixer/latest/")
fun getRatesData(
    @Query("base") base: String,
    @Query("apikey") apikey: String
): Call<CurrencyModel>

companion object {
    private const val url = "https://api.apilayer.com/"
    var apiServices: ApiServices? = null

    fun getInstance(): ApiServices {
        if (apiServices == null) {
            val retrofit = Retrofit.Builder()
                .baseUrl(url)
                .addConverterFactory(GsonConverterFactory.create())
                .build()
            apiServices = retrofit.create(ApiServices::class.java)
        }
        return apiServices!!
    }
 }
}

Repository

class CurrencyRepository constructor(private val apiServices: ApiServices) {
    fun getLatestRates() = apiServices.getRatesData("EUR", "API_KEY");
}

ViewModel

  class CurrencyViewModel constructor(private val currencyRepository: CurrencyRepository) :
    ViewModel() {
    val currencyRatesList = MutableLiveData<CurrencyModel>()
    val errorMessage = MutableLiveData<String>()

    fun getLatestRates() {
        val response = currencyRepository.getLatestRates();
        response.enqueue(object : retrofit2.Callback<CurrencyModel> {
            override fun onResponse(
                call: retrofit2.Call<CurrencyModel>,
                response: Response<CurrencyModel>
            ) {
                currencyRatesList.postValue(response.body())
            }

            override fun onFailure(call: retrofit2.Call<CurrencyModel>, t: Throwable) {
                errorMessage.postValue(t.message)
            }
        })
    }
}

FactoryViewModel

class CurrencyViewModelFactory constructor(private val repository: CurrencyRepository) :
ViewModelProvider.Factory {

override fun <T : ViewModel?> create(modelClass: Class<T>): T {
    return if (modelClass.isAssignableFrom(CurrencyViewModel::class.java)) {
        CurrencyViewModel(this.repository) as T
    }else{
        throw IllegalArgumentException("Couldn't found ViewModel")
    }
 }
}

MainActivity

class MainActivity : AppCompatActivity() {

private val retrofitService = ApiServices.getInstance()
lateinit var viewModel: CurrencyViewModel

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    viewModel = ViewModelProvider(this, CurrencyViewModelFactory(CurrencyRepository(retrofitService)))
        .get(CurrencyViewModel::class.java)
    viewModel.currencyRatesList.observe(this, Observer {
        Log.d(TAG, "onCreate: $it")
    })
    viewModel.errorMessage.observe(this, Observer {
        viewModel.getLatestRates()
    })
 }
}

CodePudding user response:

You never call viewModel.getLatestRates() in your onCreate() to fetch an initial value for your LiveData, so it never emits anything to observe. The only place you have called it is inside your error listener, which won't be called until a fetch returns an error.

Side note, I recommend naming the function "fetchLatestRates()". By convention, "get" implies that the function returns what it's getting immediately rather than passing it to a LiveData later when its ready.

And a tip. Instead of this:

class MainActivity : AppCompatActivity() {

  lateinit var viewModel: CurrencyViewModel

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // ...
    viewModel = ViewModelProvider(this, CurrencyViewModelFactory(CurrencyRepository(retrofitService)))
        .get(CurrencyViewModel::class.java)
    //...
  }
}

You can do this for the same result:

class MainActivity : AppCompatActivity() {

  val viewModel: CurrencyViewModel by viewModels(CurrencyViewModelFactory(CurrencyRepository(retrofitService)))

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // ...
  }
}
  • Related