이전글 : https://small-stepping.tistory.com/596
다음글 : https://small-stepping.tistory.com/610
1. 시간대 별로 배경 색과 박스 색이 다르다. (morning, afternoon, evening, night)
- 너무 많아서 오히려 번잡하게 느껴지나 싶어서 2개로 추릴까 생각 중이다.
2. swiperefreshlayout을 추가하여 날씨 정보를 현재 시간으로 새로고침 할 수 있게 만들었다.
이로인해 다음과 같은 우려사항이 예상되었다.
2.1 - API 정보를 불러오면서 생기는 로딩 시간에 생기는 유저의 답답함, 피로감
2.2 - 새로고침 프로그래스바의 미존재로 인한 유저의 답답함
2.3 - 새로고침이 무분별하게 반복되며 생기는 API 관련 오류
3. facebook.shimmer 라이브러리 추가 및 skeleton UI 생성
위 이미지를 참고하면 shimmer와 skeleton UI에 대해 이해할 수 있다. 둘 다 공통적으로 로딩에 관련되어있다. 이 두 항목이 중요한 이유와 어떠한 상황에 어떠한 로딩 애니메이션을 적용해야하는 지에 대해서는 다음 사이트에 잘 정리 되어 있으니 한 번 읽어보길 바란다. (https://medium.com/myrealtrip-product/상황에-맞는-로딩-애니메이션-적용하기-2018af51c197)
요약하자면, 버튼을 눌렀는데도 화면에 어떠한 변화도 일어나지 않는다면 사용자는 해당 화면이 고장났다고 느낀다. 로딩이란 사용자의 행동에 대한 피드백으로 다음 화면을 불러올 준비를 하고 있다는 것을 사용자에게 인지시킨다.
즉, 로딩은 뭔가 일 처리를 하고 있다, 우리 멈추거나 놀고 있는게 아니다 라고 사용자에게 보여주는 애니메이션 효과인 것이다. skeleton UI는 그 다음 유저에게 다가올 화면이 어떠한 화면이다 라고 알려주는 예고편이라고 할 수 있다.
완성된 로딩 화면은 다음과 같다.
4. 무분별한 새로고침 막기
이에 대해선 정확히 어떻게 처리하는 게 좋을지 모르겠어서 눈속임용 새로고침을 추가하였다. 마지막 업데이트 시간으로부터 3분이 흐른 뒤가 아니라면 로딩 애니메이션만 1.5초 재생했다가 메인 화면의 마지막 업데이트 시간만 변경하여 사용자에게 보여주는 것이다.
예를 들어 12시 44분에 업데이트를 한 상태라면 12시 47분이 되기 전까지는 아무리 업데이트를 해도 UI에 표기되는 시간만 업데이트 되고 http API 통신은 하지 않는다. 날씨 정보 앱이기에 3분 저도로 다이나믹한 일은 일어나지 않으리라 생각해서 30초도 1분도 아닌 3분으로 잡았다.
이러면 어떤 사용자는 눈치채고 불편함을 표할 수 있다고 생각되었고, 화면의 버튼, 시간별 날씨 리스트 부분을 제외한 화면을 클릭하면 기상청 메인 날씨탭에 들어가 더 자세한 정보를 확인할 수 있게 연결해 두었다. 마찬가지로 레이더 및 지도의 이미지를 누르면 기상청의 위성영상 탭에 접속되게끔 연결하였다.
5. 에러코드 정리 및 가시화
API를 5개 정도 사용하고 있고 에러가 뜨면 LogCat으로 볼 수 있는 개발환경에서와는 달리 일반 사용자는 영문도 모른채 하염없이 로딩 화면을 바라만 보고 있거나, 강제로 꺼지는 앱을 보고 있어야한다. 또한, 어디에서 봤던 말인데 '예외처리를 대충 할 것이라면 코루틴을 차라리 안쓰는게 낫다'라고 한다. 아마 에러코드 예외처리 정리하면서 봤던 글 중 하나 같은데..
이전에 예외처리라 함은 http 통신에서 CoroutineScope에 exceptionHandler를 붙이며 try/catch로 httpException, Throwable를 해놨을 뿐이었다. 이는 정상적으로 통신이 되더라도 API 내부에서 문제가 생기면 대응 할 수 없다는 뜻이기도 하다.
때문에 resultCode가 "00"(정상)이 아니라면 List<Pair<String, String>>에 에러코드와 에러가 난 API를 담게 해두었다.
awaitAll(response1, response2, response3, response4, response5).let {
loadError.postValue("")
loading.postValue(false)
val errChecker: MutableList<Pair<String, String>> = emptyList<Pair<String, String>>().toMutableList()
when {
resultUltraNcst.header.resultCode != "00" -> errChecker += Pair(resultUltraNcst.header.resultCode, "UltraSrtNcst")
resultUltraFcst.header.resultCode != "00" -> errChecker += Pair(resultUltraFcst.header.resultCode, "UltraSrtFcst")
resultHL.header.resultCode != "00" -> errChecker += Pair(resultHL.header.resultCode, "VilageFcst_YesterDay")
resultVilage.header.resultCode != "00" -> errChecker += Pair(resultVilage.header.resultCode, "VilageFcst_Today")
resultMid.header.resultCode != "00" -> errChecker += Pair(resultMid.header.resultCode, "MidFcst")
resultSatlit.header.resultCode != "00" -> errChecker += Pair(resultSatlit.header.resultCode, "SatlitImgInfoService")
}
if (errChecker.isEmpty()) setupView(binding) else errorCode(errChecker, binding)
}
위 코드를 거쳐 아래의 사진과 같이 에러코드에 따라 에러 내용을 반환하고 사용자에게는 다이얼로그가 나타나게 만들어 두었다. 여기서 심화해서 나간다면 문의하기 버튼으로 이어지게 만들어 버튼을 누르면 해당 화면을 캡쳐한 뒤 바로 개발자 이메일로 연결되는 메일쓰기로 화면으로 넘어가게 할 수도 있을 것이다. 현재는 그렇게 해두진 않았다.
또한 쓰면서 떠오른 것인데 에러코드를 저렇게 반환하여 그에 맞는 메시지를 다시 변환하는게 아니라 처음부터 resultMessage를 반환하면 되지 않을까 싶기도 하다...
6. TimeMaker 클래스 정리
현재 날짜를 가져오기 위한 함수가 있는데 API마다 초기화 시간, 날짜 등등이 전부 달라서 따로 TimeMaker라는 class를 만들어 관리하고 있다. 작성하다보니 중복되는 코드도 존재하고 불필요하게 MainActivity나 ViewModel 쪽에서 사용된 코드가 존재했는데 이를 정리하였다.
이제 gps 추가를 통한 내 위치 기준 날씨 가져오기 및 주간 날씨 Activity에 데이터 넣어주기 두 개만 하고 나면 날씨 앱은 어느정도 마무리 될 것 같다.
'개발 > 안드로이드' 카테고리의 다른 글
UI 공부 (0) | 2024.01.16 |
---|---|
날씨 앱 기록 03 (1) | 2023.10.20 |
날씨 앱 기록 01 (1) | 2023.10.06 |
kapt에서 KSP로 이전 (0) | 2023.10.05 |
AndroidStudio에서 API Key, Auth Key 관리하기 (0) | 2023.09.19 |
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!