Android/Kotlin

안드로이드 Retrofit Network Handling

easy-1 2021. 11. 4. 18:35

<개요>

Retrofit을 사용하여 서버통신 호출 시 네트워크 연결이 끊어진 경우 IOException 이 발생하며 앱 크래쉬가 일어나는  현상을 겪음

네트워크 연결이 끊어진 경우 간단한 Toast 메세지로 네트워크 연결 안내를 띄우고자함


<적용방법>

1. IOException() 클래스를 상속받아 리턴해줄 메세지 생성

object NotConnectException : IOException() {

    override val message: String
        get() = "네트워크 연결이 원활하지 않습니다."
}

2. Interceptor 를 상속받아 IOException intercept 진행

object NetworkConnectionInterceptor : Interceptor {

    override fun intercept(chain: Interceptor.Chain): Response {
        if (!isInternetAvailable()) {
            throw NotConnectException
        }

        val builder: Request.Builder = chain.request().newBuilder()
        return chain.proceed(builder.build())
    }

    // 네트워크 연결상태
    private fun isInternetAvailable(): Boolean {
        var result = false
        val connectivityManager =
            ApplicationContext().getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
        val networkCapabilities = connectivityManager.activeNetwork ?: return false
        val actNw =
            connectivityManager.getNetworkCapabilities(networkCapabilities) ?: return false
        result = when {
            actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
            actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
            actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
            else -> false
        }

        return result
    }
}

3. OkHttpClient에 NetworkConnectionInterceptor 클래스 추가

@Module
@InstallIn(SingletonComponent::class) //전체 application 에서 사용되는 모듈
object NetworkModule {


    @Provides
    @Singleton
    fun provideRetrofitRepository(retrofit: Retrofit): RetrofitService {
        return retrofit.create(RetrofitService::class.java)
    }


    @Provides
    @Singleton
    fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create())
            .baseUrl(RetrofitService.BASE_URL)
            .client(okHttpClient)
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build()
    }


    @Provides
    @Singleton
    fun provideOkHttpClient(interceptors: ArrayList<Interceptor>): OkHttpClient {
        val clientBuilder = OkHttpClient
            .Builder()
            .followRedirects(false)
        interceptors.forEach {
            clientBuilder.addInterceptor(it)
            // 네트워크 인터셉터 추가
            clientBuilder.addInterceptor(NetworkConnectionInterceptor)
        }
        return clientBuilder.build()
    }


    @Provides
    @Singleton
    fun provideInterceptors(): ArrayList<Interceptor> {
        val interceptors = arrayListOf<Interceptor>()
        val loggingInterceptor = HttpLoggingInterceptor().apply {
            level = if (BuildConfig.DEBUG) {
                HttpLoggingInterceptor.Level.BODY
            } else {
                HttpLoggingInterceptor.Level.NONE
            }
        }
        interceptors.add(loggingInterceptor)
        return interceptors
    }
}

4. 서버통신 호출하는 부분에서 토스트메세지 처리

    fun getDataList() {

        // 네트워크 에러 핸들링
        viewModelScope.launch {
            MainRepositoryImpl(service).getApi(USERUID.UID())
                .enqueue(object : Callback<DataList> {
                    override fun onResponse(call: Call<DataList>, response: Response<DataList>) {
                        if (response.isSuccessful) {
                            val data = response.body()
                            if (data != null) {
                                // ...
                            }
                        }
                    }

                    override fun onFailure(call: Call<QrList>, t: Throwable) {
                        // 에러처리
                        if (t is NotConnectException) {
                            // 토스트 메세지 보여줌
                            TM(t.message)
                        }
                    }
                })
        }
    }

<참고자료>

https://medium.com/programming-lite/retrofit-2-handling-network-error-defc7d373ad1

 

Retrofit 2 — Handling Network Error

Getting bored to check internet connectivity again and again ? Use Interceptor with Retrofit Service Client.

medium.com

http://dalinaum.github.io/android/2021/01/28/retrofit-does-not-need-dispachers-io.html

 

코루틴과 Retrofit를 쓸 때 디스패처는 필요없습니다.

Retrofit을 사용하며 아래와 같은 인터페이스가 있다고 합시다. interface Service { @GET("/") suspend fun body(): String @GET("/") suspend fun bodyNullable(): String? @GET("/") suspend fun response(): Response @GET("/{a}/{b}/{c}") suspend

dalinaum.github.io