#android #api #retrofit #okhttp #clean-architecture
Вопрос:
Я пытаюсь создать приложение для Android с помощью API SpaceX. Документация API SpaceX такова: https://github.com/r-spacex/SpaceX-API/blob/master/docs/v4/README.md Я также пытаюсь реализовать чистую архитектуру в своем приложении для Android. Я использую эту конечную точку: https://api.spacexdata.com/v4/launches чтобы получить данные о запусках от SpaceX. Тем не менее, я не могу понять, почему в моем приложении нет никаких ошибок, но оно не показывает данные из API. Вот ApiService
интерфейс:
interface PastLaunchApiService {
@GET("launches")
fun getPastLaunches(): Call<PastLaunchResponse>
}
Вот такой ApiConfig
класс:
class PastLaunchApiConfig {
companion object {
fun getApiService(): PastLaunchApiService{
val loggingInterceptor =
HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)
val client = OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.build()
val retrofit = Retrofit.Builder()
.baseUrl("https://api.spacexdata.com/v4/")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build()
return retrofit.create(PastLaunchApiService::class.java)
}
}
}
Вот такой DataSource
класс:
class PastLaunchDataSource: IPastLaunchDataSource {
private val _loadingStatus = MutableLiveData<Boolean>()
private val loadingStatus: LiveData<Boolean> = _loadingStatus
private val _connectionStatus = MutableLiveData<Boolean>()
private val connectionStatus: LiveData<Boolean> = _connectionStatus
private val _pastLaunchResponse = MutableLiveData<PastLaunchResponse>()
private val pastLaunchResponse: LiveData<PastLaunchResponse> = _pastLaunchResponse
override fun fetchFromApi(){
_connectionStatus.value = true
_loadingStatus.value = true
val client = PastLaunchApiConfig.getApiService().getPastLaunches()
client.enqueue(object : Callback<PastLaunchResponse> {
override fun onResponse(
call: Call<PastLaunchResponse>,
response: Response<PastLaunchResponse>
) {
if (response.isSuccessful){
val pastLaunchResponseValue = response.body()
_pastLaunchResponse.value = pastLaunchResponseValue
_loadingStatus.value = false
} else {
_connectionStatus.value = false
_loadingStatus.value = false
}
}
override fun onFailure(call: Call<PastLaunchResponse>, t: Throwable) {
_connectionStatus.value = false
_loadingStatus.value = false
}
})
}
override fun getPastLaunchFromSource(): LiveData<PastLaunchResponse> {
fetchFromApi()
return pastLaunchResponse
}
override fun getLoadingStatus(): LiveData<Boolean> {
return loadingStatus
}
override fun getConnectionStatus(): LiveData<Boolean> {
return connectionStatus
}
}
Затем исходный код данных используется в Repository
классе:
class PastLaunchRepository(private val pastLaunchDataSource: IPastLaunchDataSource):
IPastLaunchRepository {
override fun getPastLaunches(): LiveData<PastLaunchResponse> {
return pastLaunchDataSource.getPastLaunchFromSource()
}
override fun getLoadingStatus(): LiveData<Boolean> {
return pastLaunchDataSource.getLoadingStatus()
}
override fun getConnectionStatus(): LiveData<Boolean> {
return pastLaunchDataSource.getConnectionStatus()
}
}
Then the ViewModel is using the Interactor
class:
class PastLaunchInteractor(private val pastLaunchRepository: IPastLaunchRepository): PastLaunchUseCase {
override fun getPastLaunches(): LiveData<PastLaunchResponse> {
return pastLaunchRepository.getPastLaunches()
}
override fun getLoadingStatus(): LiveData<Boolean> {
return pastLaunchRepository.getLoadingStatus()
}
override fun getConnectionStatus(): LiveData<Boolean> {
return pastLaunchRepository.getConnectionStatus()
}
}
Here is the viewModel:
class PastLaunchViewModel(private val pastLaunchUseCase: PastLaunchUseCase):ViewModel() {
fun getPastLaunches(): LiveData<PastLaunchResponse> = pastLaunchUseCase.getPastLaunches()
fun getLoadingStatus(): LiveData<Boolean> = pastLaunchUseCase.getLoadingStatus()
fun getConnectionStatus(): LiveData<Boolean> = pastLaunchUseCase.getConnectionStatus()
}
And finally I’m testing whether the connection worked by displaying to a simple textview on the activity:
viewModel.getPastLaunches().observe(this,{
val data = it.pastLaunchResponse?.size.toString()
binding.tvTest.text = data
println(data)
})
The weird thing is that I got no error and the client is returning a succesful connection. This is my logcat:
2021-06-16 17:00:42.469 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: <-- 200 ************************************** (1188ms)
2021-06-16 17:00:42.469 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: access-control-allow-origin: *
2021-06-16 17:00:42.469 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: access-control-expose-headers: spacex-api-cache,spacex-api-response-time
2021-06-16 17:00:42.469 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: alt-svc: h3-29=":443"; ma=2592000,h3-34=":443"; ma=2592000,h3-32=":443"; ma=2592000
2021-06-16 17:00:42.469 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: cache-control: max-age=20
2021-06-16 17:00:42.469 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: content-security-policy: default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests
2021-06-16 17:00:42.470 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: content-type: application/json; charset=utf-8
2021-06-16 17:00:42.470 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: date: Wed, 16 Jun 2021 10:00:43 GMT
2021-06-16 17:00:42.470 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: etag: "512bd-t5u 0jrrLE3lf0AU/jfe1wPmE1s"
2021-06-16 17:00:42.470 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: expect-ct: max-age=0
2021-06-16 17:00:42.470 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: referrer-policy: no-referrer
2021-06-16 17:00:42.470 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: server: Caddy
2021-06-16 17:00:42.470 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: spacex-api-cache: MISS
2021-06-16 17:00:42.470 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: spacex-api-cache-online: true
2021-06-16 17:00:42.470 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: spacex-api-response-time: 71ms
2021-06-16 17:00:42.470 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: strict-transport-security: max-age=15552000; includeSubDomains
2021-06-16 17:00:42.470 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: vary: Origin
2021-06-16 17:00:42.470 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: vary: Accept-Encoding
2021-06-16 17:00:42.470 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: x-content-type-options: nosniff
2021-06-16 17:00:42.470 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: x-dns-prefetch-control: off
2021-06-16 17:00:42.470 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: x-download-options: noopen
2021-06-16 17:00:42.471 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: x-frame-options: SAMEORIGIN
2021-06-16 17:00:42.471 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: x-permitted-cross-domain-policies: none
2021-06-16 17:00:42.471 10480-10512/com.briancatraguna.spacex I/okhttp.OkHttpClient: x-xss-protection: 0
2021-06-16 17:00:42.808 10480-10497/com.briancatraguna.spacex W/System: A resource failed to call close.
2021-06-16 17:00:42.808 10480-10497/com.briancatraguna.spacex W/System: A resource failed to call close.