반응형

개요

 

비동기 network 환경에 최적화되어있는 라이브러리.

 

live data, room ,viewModel 패턴과 함께 사용.

 

GOOGLE에서 정식으로 채택한 NETWORK LIBRARY

 

 

공식 사이트

square.github.io/retrofit/

 

Retrofit

A type-safe HTTP client for Android and Java

square.github.io

 

구성

 

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

+ Recent posts