반응형
개요
비동기 network 환경에 최적화되어있는 라이브러리.
live data, room ,viewModel 패턴과 함께 사용.
GOOGLE에서 정식으로 채택한 NETWORK LIBRARY
공식 사이트
구성
gradle
//[network] Retrofit, Gson, RxAdapter
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
implementation "com.squareup.retrofit2:converter-gson:$retrofit_version"
implementation "com.squareup.retrofit2:adapter-rxjava2:$retrofit_version"
//[network] okhttp
implementation "com.squareup.okhttp3:okhttp:$okhttp_version"
implementation "com.squareup.okhttp3:logging-interceptor:$okhttp_version"
- version 경우 def로 버전 string값 정의 하면됨.
Result.kt
sealed class Result<out T: Any>{
data class Success<out T : Any>(val data: T) : Result<T>()
data class Error(val exception: String) : Result<Nothing>()
}
- network response object
MusicApiService.kt
public interface MusicApiService{
@GET("/2020-flo/song.json")
suspend fun fetchSong():Response<Song>
}
- 자기 통신에 맞는 uri interface 정의
NetworkContainer.kt
public class NetworkContainer {
private val interceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
private val client:OkHttpClient by lazy {
OkHttpClient.Builder()
.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
.addNetworkInterceptor(interceptor)
// .addInterceptor(new AddCookiesInterceptor(getApplicationContext()))
// .addInterceptor(new ReceivedCookiesInterceptor(getApplicationContext()))
.build()
}
private val retrofit:Retrofit by lazy{
Retrofit.Builder()
.baseUrl(NetworkContainer.MEDIA_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
fun getApiService():MusicApiService{
return retrofit.create(MusicApiService::class.java)
}
suspend fun <T : Any> safeApiCall(call: suspend () -> Response<T>): Result<T> {
return try {
val myResp = call.invoke()
if (myResp.isSuccessful) {
Result.Success(myResp.body()!!)
} else {
Result.Error(myResp.errorBody()?.string() ?: "Something goes wrong")
}
} catch (e: Exception) {
Result.Error(e.message ?: "Internet error runs")
}
}
public suspend fun fetchSong():Result<Song>{
return this.safeApiCall(call = { getApiService().fetchSong() } )
}
companion object{
val CONNECT_TIMEOUT = 5000L
val WRITE_TIMEOUT = 5000L
val READ_TIMEOUT = 5000L
val MEDIA_URL = "custom url"
}
}
- getApitService()로 미리 정의 해둔 api interface를 전달.
- 컴파일시 정확한 내용 전달을 위해 safeApiCall()로 한번 감싸줌.
- fetchSong 부분이 실제적인 호출 부분.
SongViewModel.kt
class SongViewModel(val networkContainer:NetworkContainer) :ViewModel(){
private val song: MutableLiveData<Song> by lazy {
MutableLiveData<Song>()
}
fun getSong(): LiveData<Song> {
return song
}
val errorMessage: MutableLiveData<String> by lazy {
MutableLiveData<String>()
}
fun fetchSong() {
viewModelScope.launch {
val result = networkContainer.fetchSong()
when(result){
is Result.Success ->{
song.postValue(result.data)
}
is Result.Error -> {
errorMessage.postValue(result.exception)
}
}
}
}
}
- ViewModel을 상속받은 클래스로 위에서 정의했던 NetworkContainer가저옴.
- fetchSong()으로 결과값 가저오기.
- when .. is 조합으로 타입 검사후 결과값이 Success인지 Error인지 구분함
- postValue를 통해 observe하고있는 class쪽에 알림
추가옵션
viewModel사용시 provider를 생성하지않고 viewModels를 사용해 객체를 생성할때 parameter를 넘기려면 아래같이 작업해 줘야한다.
SongViewModelFactory.kt
class SongViewModelFactory(val networkContainer: NetworkContainer) : ViewModelProvider.Factory{
override fun <T : ViewModel?> create(modelClass: Class<T>): T = modelClass.getConstructor(networkContainer::class.java).newInstance(networkContainer)
}
Activity
/**
* network viewmodel
*/
val songVM by viewModels<SongViewModel>{
SongViewModelFactory(networkContainer)
}
//observe network viewModel
songVM.getSong().observe(this, Observer {
})
반응형
'AOS' 카테고리의 다른 글
(안드로이드) git 꼬엿을때. (0) | 2021.06.02 |
---|---|
(안드로이드) constraintLayout animation (0) | 2021.06.01 |
(Android) 트위치 app 2 - ANR WatchDog (0) | 2021.04.16 |
(안드로이드)채팅 구현하기 (0) | 2021.01.14 |
(안드로이드) jobService (0) | 2020.10.15 |