안드로이드

[Kotlin/Android] Internet Connect (4) Error Handling with Status

란서 2022. 1. 20. 10:44

처음부터 인터넷 연결이 되지 않았을 때 또는 로딩 중 일 때 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 재요청하게끔