디자인 패턴 공부를 미뤄왔었습니다.
귀찮기도 했고, 무엇보다 기능 구현을 우선으로 여겨, 여러 자잘한 버그들을 수정하고 보완하는데 시간을 보냈습니다.
필요한 라이브러리 기술들을 살펴보려 예시 앱들을 찬찬히 뜯어보는데,
모두 MVVM 아키텍처 기반으로 구성되어 있어, 무지했던 저는 알아보기 힘들었습니다.
이번 기회에 본격적으로 공부도 할 겸, 기존 앱에 MVVM 패턴을 적용해 봤습니다.
다음은 수정한 굵직한 부분입니다.
데이터 계층 정의
이전까지는 각 프레그먼트에서 각 라이브러리(Retrofit2, RoomDB) 의 매서드를 통해 데이터를 요청했습니다.
필요한 데이터 유형이 같은 경우, 데이터를 요청하는 메서드를 복붙 하여 사용했으며
데이터터 요청 방식이 달라질 경우, 모든 코드를 하나하나 수정해야 했습니다.
위 사진과 같이 각 데이터 유형별로 리포지토리를 정의했고,
뷰모델에서 해당 리포지토리의 매소드를 갖다 쓰는 방식으로 수정했습니다.
Application Class를 통해 Room, Retrofit 인스턴스를 싱글톤으로 초기화시켰고,
각 리포지토리에 인자로 전달했습니다.
뷰 모델 정의
가장 고민을 많이 했던 부분이었습니다.
저는 하나의 액티비티를 사용하며, 프레그먼트 내의 프레그먼트를 여러 개 중첩시키는 구조를 가지고 있습니다.
독립적인 뷰모델을 갖게 할 것인지, 부모 프레그먼트 별로 뷰모델을 갖게 할 것인지 등등
뷰모델의 단위를 정하기가 어려웠습니다.
각 독립적인 프레그먼트마다 요구하는 데이터가 다르기 때문에,
각각의 프레그먼트가 뷰 모델을 갖도록 결정했습니다.
프레그먼트 간의 데이터 공유가 필요하기 때문에,
Activity 단위의 SharedViewModel을 만들었습니다.
프레그먼트에서는 SharedViewModel의 해당 LiveData 변수를 Observe 하여
필요한 데이터를 요청하게끔 작성하였습니다.
밑에는 그 예시입니다.
채널을 조회하는 프레그먼트의 뷰 모델입니다.
채널 내 비디오를 요청하는 매소드를 가지고 있습니다.
채널프레그먼트입니다.
sharedViewModel의 channelData를 observe 하여
뷰모델의 fetch 함수를 호출합니다.
가장 까다로웠던 부분은 비디오 재생 프레그먼트의 작동 방식이었습니다.
플레이리스트 내의 비디오를 재생했을 때와, 단일 비디오를 재생했을 때
비디오 재생 프레그먼트의 동작 방식은 달라야 합니다.
또한 플레이리스트에서 현재 재생 중인 곡에 대한 접근을 쉽게 하기 위해,
NowPlaylistModel 클래스를 만들어 컨트롤합니다.
이전에는 비디오 재생 프레그먼트를 생성할 때, Bundle을 통해 NowPlaylistModel 객체를 전달하며
그 값이 null이냐 아니냐를 통해 작동 방식을 결정했습니다.
데이터 공유를 위해 SharedViewModel에 NowPlaylistModel을 둬야 했는데,
이럴 거면 굳이 비디오 재생 프레그먼트의 뷰모델을 만들어야 하는 생각이 들었습니다.
또한 해당 기능은 액티비티 내의 뷰를 참조하여 이용해야 했었고,
비디오 재생에 필요한 Player 객체도 바인드 서비스의 객체를 지니고 있는 액티비티로부터 가져와야 했기에 더욱 혼란스러웠습니다.
고민 끝에, 다음과 같은 이유로 재생 프레그먼트 또한 뷰모델을 두는 것으로 결정했습니다.
1. 독립성
기존의 독립적으로 설계한 뷰모델들의 의미가 퇴색될 것이라 생각했습니다.
2. Player 객체 획득 방식 변경
기존에는 Bind Service를 이용하고 있었으며, 액티비티와 서비스가 바인드 될 경우
서비스로부터 Player 객체를 얻으며 프레그먼트의 playerView와 연결해 주었습니다.
최근에 업데이트된 media3의 MediaSessionService로 변경하는 과정에서
Player 객체와 프레그먼트의 playerView를 연결하는 방식이 간소화되었습니다.
이 부분은 다음에 포스팅하겠습니다.
3. UI 로직
비디오 재생 프레그먼트 내의 UI 로직이 많이 복잡합니다.
UI 변경 관련 홀더가 필요했습니다.
열거형 클래스로 PlaybackMode를 정의했습니다.
해당 모드에 따라 옵저버를 따로 설정해 주었으며,
코드를 올리지 않았지만, 뷰 또한 모드에 따라 나누어 설정해 주었습니다.
클래스들을 각 역할에 맞게 정리하였습니다.
network 에는 Retrofit 관련 파일들과, 데이터를 받아올 dto로 구성되어 있습니다.
others 에는 Constant 파일과 문서들로 구성되어 있습니다.
service 에는 미디어 재생을 위한 MediaSessionService 파일이 존재합니다.
utils 에는 앱 사용 시간 체크, 유튜브 숫자 계산 로직, 데이터 모델 매핑 클래스 등으로 구성되어 있습니다.
view 에는 액티비티, 프레그먼트, 어댑터 등으로 구성되어 있습니다.
결론
미숙했지만, 이론으로 공부해 보는 것보다 직접 활용해 보며 공부하는 것이 곱절로 이해가 잘 갔습니다.
특히 이미 작성했던 코드를 수정해 봄으로써 MVVM 패턴만의 장점을 몸소 느끼며 흐름을 파악할 수 있었습니다.
아직은 그렇다 할 확신이 없기 때문에,
여러 프로젝트 예시들을 참고해 보며 더 공부해야 할 필요성을 느끼게 되었습니다.
'안드로이드 프로젝트 > 유튜브 음정 조절 어플리케이션' 카테고리의 다른 글
[Android] # 14 Navigation Component 사용하기 (3) | 2023.08.25 |
---|---|
[Android] # 문제 해결 - 6 Room 마이그레이션 실수.. (0) | 2023.07.06 |
[Android] # 문제 해결 - 5 앱 이슈 해결 (0) | 2023.07.01 |
[Android] #12 mediaSession 공부 및 코드 리팩토링 - 1 (0) | 2023.06.29 |
[Android] #11 Youtube data api 할당량 최적화 (데이터 캐싱) (0) | 2023.06.27 |
댓글