이번에 java로 짜여진 앱을 Kotlin으로 마이그레이션하면서 겪은 이야기를 기록하려고합니다.
- asyncTask를 Coroutine으로 대체했습니다.
- 복잡한 if else 문은 when으로 대체했습니다.
- 큰 메서드를 여러 메서드로 분리했습니다.
- 코드의 의미를 한눈에 알 수 있도록 메서드를 이용해 추상화했습니다.
- run, apply, use 등의 확장함수를 사용해서 가독성을 높였습니다. 중복을 제거했습니다.
1. asyncTask를 Coroutine 으로 대체하기
이미지를 다운로드 하는 ImageDownloader라는 asyncTask가 있었습니다.
asyncTask에는 네가지 함수가 오버라이딩 되있었습니다.
- onPreExecute()
- doInBackground(String... params)
- onProgressUpdate(Integer... progress)
- onPostExecute(Bitmap result)
먼저 이 거대한 asyncTask를 여러 함수로 나누기로 했습니다.
먼저 downloadImage라는 함수를 만들고, 그 안에서 코루틴을 돌렸습니다.
private fun downloadImage(imageUrl: String) {
lifecycleScope.launch(Dispatchers.Main) {
//download image
}
activity에서 돌리는 코루틴이였으므로, 라이프사이클에 따라서 자동으로 취소되도록 lifecycleScope를 이용하였습니다.
또한 이미지 다운로드 중에 진행도를 UI에 표시할 필요가 있었기 때문에 Dispatchers.Main을 사용해 메인스레드에서 코루틴을 실행하도록 했습니다.
위에서 정의한 코루틴 스코프를 이용하면 asyncTask에서 할 수 있는건 모두 할 수 있습니다.
private fun downloadImage(imageUrl: String) {
lifecycleScope.launch(Dispatchers.Main) {
//onPreExecute
val bitmap = withContext(Dispatchers.IO) {
//doInBackground
}
//onPostExecute
}
}
주석이 있는 위치를 이용하면 asyncTask의 함수를 이용하는 것과 같은 효과를 볼 수 있습니다.
onProgressUpdate의 경우에는 아래처럼 함수를 만든뒤,
suspend fun getBitmapFromUrl(imageUrl: String, updateUI : (progress : Int) -> Unit): Bitmap? {
while(/*읽을 바이트가 있을때*/){
//이미지 받아오기
withContext(Dispather.IO){
updateUI(/*진행도*/)
}
}
}
아래처럼 사용하면 될것입니다.
private fun downloadImage(imageUrl: String) {
lifecycleScope.launch(Dispatchers.Main) {
//onPreExecute
val bitmap = withContext(Dispatchers.IO) {
//doInBackground
getBitmapFromUrl(imageUrl) { progress->
//update ui
}
}
//onPostExecute
}
}
'안드로이드 앱개발' 카테고리의 다른 글
클린아키텍쳐에서의 usecase 분리 (0) | 2021.04.27 |
---|---|
안드로이드 앱개발에서의 클린아키텍쳐 (0) | 2021.04.17 |
동영상 스플래시 스크린 띄우기 (동영상에 애니메이션 넣기) (0) | 2021.04.03 |
Firebase를 이용해 FCM 구현하기(웹서버 이용) (0) | 2021.01.08 |
브로드캐스트(android studio Broadcast) (0) | 2021.01.05 |