Reputation: 3
I am trying to retrieve/fetch data from server using retrofit and Rxjava to show data in recycler view. The code do not detect any error but still no data is shown. please check my code and help where am I mistaken. Here is my API https://www.testing.albassamapp.com/api/familymembers/v2
Here is my data class Code:
data class Profile(
@SerializedName("id")
val id: Int,
@SerializedName("name")
val name: String,
@SerializedName("father_name")
val fatherName: String,
@SerializedName("profile_picture_square")
val profilePicture: String
)
Here is my interface:
interface ProfileApi {
@GET("familymembers/v2")
//single is observable it emit one variable and then close
fun getProfiles(): Single<List<Profile>>
}
Here is my service class:
class ProfileService {
private val BASE_URL = "https://www.testing.albassamapp.com/api/"
private val api:ProfileApi
init {
api = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
.create(ProfileApi::class.java)
}
fun getProfile(): Single<List<Profile>> {
return api.getProfiles()
}
}
Here is my listViewModel:
class ListViewModel:ViewModel() {
private val profileService = ProfileService()
private val disposable = CompositeDisposable()
//for live data
val profiles = MutableLiveData<List<Profile>>()
val profileLoadingError = MutableLiveData<Boolean>()
val loading = MutableLiveData<Boolean>()
fun refresh() {
fetchProfiles()
}
private fun fetchProfiles() {
loading.value = true
disposable.add(
profileService.getProfile()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(object : DisposableSingleObserver<List<Profile>>() {
override fun onSuccess(value: List<Profile>?) {
profiles.value = value
profileLoadingError.value = false
loading.value = false
}
override fun onError(e: Throwable?) {
profileLoadingError.value = true
loading.value = false
}
})
)
}
override fun onCleared() {
disposable.clear()
}
}
Upvotes: 0
Views: 820
Reputation: 1363
You have one mistake serlizable is wrong based on reponse for api, api response is json object contain list of profile you change return in api interface First create object
this your data class
data class Profile(
@SerializedName("id")
val id: Int,
@SerializedName("name")
val name: String,
@SerializedName("father_name")
val fatherName: String,
@SerializedName("profile_picture_square")
val profilePicture: String
)
Add new class in your data class
data class Result(
@SerializedName("Status")
val status: Int,
@SerializedName("Message")
val message: String,
@SerializedName("Data")
val data: List<Profile>
)
your interface will be like this after change
interface ProfileApi {
@GET("familymembers/v2")
//single is observable it emit one variable and then close
fun getProfiles(): Single<Result>
}
your service will be like this
class ProfileService {
private val BASE_URL = "https://www.testing.albassamapp.com/api/"
private val api:ProfileApi
init {
api = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
.create(ProfileApi::class.java)
}
fun getProfile(): Single<Result> {
return api.getProfiles()
}
}
your view model will be like this
class ListViewModel: ViewModel() {
private val profileService = ProfileService()
private val disposable = CompositeDisposable()
//for live data
val profiles = MutableLiveData<List<Profile>>()
val profileLoadingError = MutableLiveData<Boolean>()
val loading = MutableLiveData<Boolean>()
fun refresh() {
fetchProfiles()
}
private fun fetchProfiles() {
loading.value = true
disposable.add(
profileService.getProfile()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(object : DisposableSingleObserver<Result>() {
override fun onSuccess(result: Result) {
if(result.status==200){
profiles.value = result.data
profileLoadingError.value = false
}else{
// in case exception or message
profileLoadingError.value = true
}
loading.value = false
}
override fun onError(e: Throwable) {
profileLoadingError.value = true
loading.value = false
}
})
)
}
override fun onCleared() {
disposable.clear()
}
}
Upvotes: 1
Reputation: 3566
I have modified @yousef's answer above to the following because I could not edit for some reason and the English is a little unclear
You have one mistake the model is wrong based on response for api, api response is json object that contains list of other model object say Profile
you must change the returned model in api interface like
First create model Result
data class Result(
@SerializedName("Status")
val status: Int,
@SerializedName("Data")
val data: List<Profile>
)
and then make a Profile
class like so
data class Profile(
@SerializedName("id")
val id: Int
@SerializedName("parent_id")
val parentId: Int // and so on based on the fields you need
)
Just change in your interface for api take object result like this
fun getProfiles(): Single<Result>.
And then accordingly this will change the other code and you can get the List<Profile>
property of the Result
class by using getters which are provided by default in the data class of Kotlin
Additionally to reduce the headache while making a model from json, You can use websites like Json2Kotlin
Upvotes: 1