오늘은 콜백 함수에 대해 공부하기로 했다.
사실 이번에 토이 프로젝트를 하기 전까지는 콜백 함수가 뭔지 몰랐다.
아니 존재 자체도 몰랐다.
보고 따라 사용하면서도 내가 잘 이해하면서 쓰고 있는 건가..? 싶었다.
예전에 오픈 채팅방에 뭘 물어봤었는데 이런 답변을 해주신 분이 계셨다
정곡을 찔린듯한 기분이 들었다.
"인터넷보고 따라 작성해서 어찌저찌 코드는 돌아갔다고 해도 그건 니 코드가 아니다"를 좋게 말씀해주신 것 같다.
그래서 오늘은 콜백 함수 파헤치기!! 빠밤
1. 이해하기 쉽게 실생활에 빗대어 만화로 그려보았다.
이렇게 해서 모두가 행복하게 살았답니다(?) 끝 -!
불쌍한 우리 메인작가...
모든걸 혼자서 다 하기엔 시간이 오래 걸리는 모양이다.
결국 원고도 못 그리고 큰일날 뻔했지만
보조작가의 도움으로 오래걸리는 작업은 맡겨두고, 계속해서 원고를 그려나갈 수 있었다.
보조작가가 작업이 다 끝나면 전화를 해주기로 했다.
전화를 받으면 그때 그 스토리로 다음 원고를 그려나가기로 했다.
이 이야기에는 동기/비동기 그리고 콜백 함수의 개념이 녹아들어 있다.
그럼 이제 프로그래밍 관점에서 이야기를 다시 보자!
2. 프로그래밍 관점으로 이야기를 바꿔보았다.
이렇듯 메인 스레드에게 네트워크나 DB작업 같이 오래 걸리는 일을 맡기는 건 옳은 방법이 아니다.
사용자는 UI가 그려질 때까지 백날이고 천날이고 기다려주지 않기 때문이다.
그래서 우리는 메인 스레드 외에 다른 스레드를 사용하는 것이고
그 스레드에게 일을 시켜놓고 내 할 일을 하는 것이 비동기인 것이다.
(내가 그 일을 순서대로 진행하면 동기)
그리고 마지막으로...
다른 스레드에게 일을 시켜놓고 메인 스레드는 계속해서 UI를 그려나간다.
작업을 다 마친 스레드가 결과물을 메인 스레드에게 넘겨주면
메인 스레드는 그걸 이용해서 UI를 그린다.
이때 "메인 스레드님!! 저 작업 다 끝났어요!!라고 하는 게 콜백인 것이다.
3. 콜백 함수를 사용한 실제 예시
recyclerView_notices.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
if (!recyclerView_notices.canScrollVertically(1){
공지사항을 불러옴(네트워크 작업)
리스트에 공지사항을 추가하고 새로고침(UI 작업)
}
})
위 코드를 작성하면서 콜백 함수의 필요성을 느끼게 되었다.
recyclerView의 끝에 도달하면 네트워크에서 다음 공지사항을 가져와서 화면에 보여주는 코드이다.
네트워크 작업이 오래 걸리기 때문에 UI 작업이 먼저 실행되었고
그 결과 오류가 생기는 일이 발생했다.
(혹시 위 코드에 대한 자세한 내용이 궁금하다면 여기서 다루고 있다)
interface PostListener {
fun loadPage(notices: ArrayList<NoticeList>)
}
아무튼...
그래서 네트워크 작업이 끝나면 콜백을 해서 UI 작업을 하도록 해야 했다.
그러기 위해서는 우선 콜백 함수를 만들어야 한다. 여기서는 loadPage라는 이름으로 정했다.
이 loadPage는 메인 액티비티에서 정의할 것이므로 interface안에 선언한다.
class MainActivity : AppCompatActivity(), PostListener { // PostListener를 구현한다.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
recyclerView_notices.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
if (!recyclerView_notices.canScrollVertically(1){
네트워크 작업(this) // this는 listener를 뜻한다.
// 여기서 했던 UI 작업을 loadPage 함수에서 한다.
}
}
})
}
override fun loadPage(notices: ArrayList<NoticeList>) { // override 함
UI 작업
}
}
메인 액티비티에서 PostListener를 구현하고 loadPage를 재정의 해준다.
그러면 이제 리스트 UI 작업은 별도의 함수에서 정의되어있고
콜백을 받았을 때 실행 되게 될 것이다.
class 네트워크 작업(listener: PostListener){
var mCallback = listener
...
...
...
mCallback.loadPage(notices) // 작업이 다 끝나고 loadPage를 호출한다.
}
네트워크 작업을 하는 곳에서 뚝딱뚝딱 일을 처리해서
공지사항 목록인 notices를 만들고
그 결과물을 loadPage를 통해 넘겨주게 된다.
이제 비로소 UI 작업을 할 수 있게 되는 것이다.
참고한 영상
https://www.youtube.com/watch?v=s1vpVCrT8f4
https://www.youtube.com/watch?v=jjypeFGJC3c
비동기 처리도 배우고 가셔유!
'오늘은 뭘 배울까? > Android' 카테고리의 다른 글
안드로이드 뷰 바인딩(view binding) (6) | 2021.03.05 |
---|---|
[Kotlin] 뷰페이저2 활용 예제 : tabLayout, indicator, fragment, 자동 스크롤, 무한스크롤, 배너 등 (13) | 2021.02.27 |
코틀린 viewPager2 : 사용법, 애니메이션 등 (50) | 2021.02.24 |
안드로이드 액티비티 생명주기 (Activity Life cycle) (10) | 2021.02.23 |
[kotlin] 코루틴 공부하기 (비동기 처리, 서버 딜레이 처리) (12) | 2021.02.14 |
댓글