[Kotlin/Android] Internet Connect (4) Error Handling with Status
처음부터 인터넷 연결이 되지 않았을 때 또는 로딩 중 일 때 Error Handling
이게 무슨말인가 하면,, 지금까지 Glide 라이브러리를 통해 web server로 부터 받아온 Image Url을 통해 image 를 로드하여 ImageView에 로드하는 과정을 (3)에서 했다. 또한 해당 이미지 로드에 실패하거나 (도중 인터넷 연결이 끊겨서) 이미지를 로딩 중 일때 placeholder와 error 일 때 이미지까지 설정하였다.
하지만 애초부터 인터넷이 끊긴상태로 접속하게 되면 그 어떠한 상태 이미지 없이 하얀색 배경화면만 있는 모습을 볼 수 있다.
이처럼 비행기 모드일 때는 web server에 대한 요청이 이루어지지 않기 때문에 어플리케이션은 어떠한 작동도 없어서 사용자를 당황시킬 수 있다. 따라서 유저의 앱 만족도를 높이기 위해서는 인터넷 연결이 불가능할 때, 또는 인터넷에 연결 중일 때 (web service를 요청할때) 등 어떤 상태인지 인식시킬 수 있는 코드를 구현할 필요가 있다.
Add Status To ViewModel (enum class)
우선 viewModel에 현재 앱상태를 나타낼 수 있는 status 프로퍼티를 만들어 앱이 웹 서비스를 요청하여 이미지를 로딩중일 때, 에러가 났을 때, 인터넷 연결이 완료됐을 때를 가리킬 수 있게 해야한다.
- 이러한 3가지 상태 (에러,로딩,완료) 를 나타내는 enum class MarsApiStatus 와 해당 클래스를 타입으로 갖는 LiveData<MarsApiStatus> 변수 status를 만들어 구현해보자.
//In OverViewModel, Top-level class
enum class MarsApiStatus {
LOADING,
DONE,
ERROR
}
//In OverViewModel, new property
private val _status = MutableLiveData<MarsApiStatus>()
val status : LiveData<MarsApiStatus>
get() = _status
- fun getMarsRealestateProperties() 메서드 내에서 앱이 로딩중일 때, 완료했을 때, 에러 났을 때 각각 status의 value 값을 설정해주도록 하자.
fun getRealestateProperities() {
viewmodelScope.launch{
_status.value = MarsApiStatus.LOADING
try{
_status.value = MarsApiStatus.DONE
_property.value = MarsApi.retrofitService.getProperty()
} catch(e:Exception) {
_status.value = MarsApiStatus.ERROR
}
}
}
이처럼 각각 try/catch 구문 이전에는 로딩중, try내에서는 완료, catch내에서는 에러 값으로 초기화한다.
- BindingAdapter를 이용하여 status의 값에 따라 ImageView가 각기 다른 이미지를 display
@BindingAdapter("marsApiStatus")
fun bindStatus(statusImgView:ImageView, status:MarsApiStatus) {
when(status) {
DONE -> {
statusImgView.visibility = GONE
}
LOADING -> {
statusImgView.visibility = VISIBLE
statusImgView.setImageResource(R.drawable.loading_animation)
}
ERROR -> {
statusImgView.visibility = VISIBLE
statusImgView.setImageResource(R.drawable.Ic_connection_error)
}
}
}
-DONE(완료) : 완료 상태일 때는 이미 리사이클러뷰에 로드된 많은 이미지들이 디스플레이 되고 있기 때문에 굳이 로드됐다라는 이미지를 보여줄 필요가 없기에 GONE
-LOADING, ERROR : 해당 상태일 때는 이제 리사이클러뷰가 나타나지 않기 때문에 별도의 이미지뷰를 이용하여 상태 이미지를 DISPLAY한다.
- In fragment_overview.xml, constraintLayout 내에 새로운 ImageView를 생성하고, 해당 ImageView에 marsApiStatus attr 을 설정한다.
//In fragment_overview.xml
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.android.marsrealestate.MainActivity">
<androidx.recyclerview.widget.RecyclerView
...
/>
<ImageView
android:id="@+id/status_image"
android:onClick="@{()->viewModel.onClick()}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
marsApiStatus="@{viewModel.status}"/>
</androidx.constraintlayout.widget.ConstraintLayout>
완료.
추가 Custom : 비행기모드에서 다시 데이터 연결 시, 이미지뷰 클릭하면 web service 재요청하게끔