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
http://dalinaum.github.io/android/2021/01/28/retrofit-does-not-need-dispachers-io.html