Android Developer UI Layer 공식문서
->https://developer.android.com/jetpack/guide/ui-layer?hl=ko
위그림에서 ViewModel위에 DomainLayer라고 작성되어있는데 보통 ViewModel은 UI Layer에 넣는경우가 많고 이렇게 하는 것이 AndroidJetpack의 설계원치게 더 부합한다. 하지만 ViewModel에서 재사용되는 간단한 비즈니스로직들은 DomainLayer에 넣을 수 도 있기도 해서 일단은 사진에서는 DomainLayer라고 작성했는데 괜히 저렇게 그린것 같다는 생각이 아무리봐도 계속들어서 사진을 다시 올려야겠다...아핫..!!ㅋㅋ 아래 사진은 증거사진임 ㅋㅎ
-State Holder : 상위개념 / View : 하위개념
-상위모듈은 하위모듈로 부터 상태를 직접적으로 읽을 수 없다. 심지어 존재조차도 모르게 하는것이 제일 좋다. 반대로 하위모듈은 상위모듈로부터 이벤트를 직접 읽을 수 없다.
-상위모듈은 하위모듈에 의존성을 갖지 않는다. : 상태변경을 통제할 필요가 없으니까 굳이 의존성을 가질 필요가 없다.
-반대로 하위모듈은 상위모듈에 의존성을 갖는다. 단, 전달만 할 뿐이고 직접적으로 결과를 받는 것이아니라 구독에 대한 통보만을 받는다.
-반드시 StateHolder와 View에서만 적용이 된다는 의미가 아니고 상위개념과 하위개념의 예시로서 StateHolder와 View가 사용된거야.
-상위모듈은 하위모듈에 대해서 모르는 상태에서 이벤트만 발생시킨다. 예를들어 유저가 무언가 클릭했을 때 하위개념이 요청을 상위개념으로 보내면 상위 개념은 이벤트만 발생시킨다.
-하위 모듈은 어떤일이 일어났을 때 상위개념으로 요청을 보낸다. 즉, 상위 모듈은 하위 모듈에 의존성이 없고 , 하위 모듈은 상위 모듈에 의존성이 있다.
-View를 완벽하게 수동적으로 만들기 위한 구조
-UDF 원칙
상위객체는 하위 객체로부터 상태를 직접 읽을 수 없어야 한다. 직접 읽는 대신에 필요한 데이터는 정의된 인터페이스 또는 메서드를 통해서 전달 받아야 된다.
하위객체는 상위 객체의 이벤트를 직접 읽을 수 없고 , 상위 객체도 하위 객체로 직접 이벤트를 보낼 수도 없다.
상태를 관리하는 객체(State Holder)는 View 방향으로의 의존성을 갖지 않는다.
-View는 자신이 받은 사용자 입력을 전달만 할 뿐 직접적으로 결과를 받지 않는다. 대신 간접적으로 이벤트 형태로 상태 변경을 통보 받는다.
-StateHolder : 앱의 상태 , 화면의 상태..등등의 모든 상태를 다 가지고 있어서 임의의 상태에서 어떤 일이 발생했을 때 상태변경을 View에게 알려준다. 이때 알려주는 방식은 콜백이나 비동기적인 이벤트들을 View가 구독을 하면 이벤트들로부터 값을 받는다. 따라서 직접적으로는 StateHolder는 View에대해서 모른다.
-마틴 파울러가 만든 Presentation Domain Separation(PDS)가 시초이다. 그러다가 마소에서 데이터 바인딩 개념을 PDS에 추가해서 MVVM 이라는 패턴을 만들었다.
-cf.DataBindig : View에 어떤 정보가 바뀌어야 된다든가 하는 것들을 ViewModel이 이해하고 있어서 , ViewModel이 View에게 특정 부분에 대한 값을 바꾸라고 하면 View에서 바로 값을 바꾸도록 하는것을 의미한다.
-ViewModel은 그 자체로 독립적인 시스템이다.
-결과를 이벤트로 보내기만 하고 받는 사람이 있을 거라는 걸 모른다. 따라서 View의 유형이 바뀌어도 ViewModel은 모르기 때문에 하나의 ViewModel에 여러개의 View를 사용해도 된다.
-ViewModel을 테스트 할 때에도 ViewModel에 있는 특정 이벤트들을 구독하고 있는 형태로 해놓고 특정 함수를 호출 했을 때 특정 이벤트가 나오는지에 대한 형태로 구현하면 쉽게 구현이 가능하다. 왜냐하면 ViewModel은 View가 존재하지 않아도 동작할 수 있는 독립적인 시스템이기 때문이다.
-이벤트를 View에 바로 적용할 수 있게 도와준다.
<CheckBox
android:id = "@+id/rememberMeCheckBox"
android:checked = "@{viewmodel.rememberMe}"
android:onCheckedChanged = "@{(v,checked)->viewmodel.rememberMeChanged(checked)}" />
-기본적으로 이벤트를 비동기적으로 구독해서 받는 형태인데 이런것들을 반응형 프로그래밍이라고 한다. 그런데 이러한 반응형들은 코드상에서 직관적이지도 않고 어려워
-모든 로직들을 ViewModel로 위임시켰기 때문에 로직의 사이즈가 커지면 필연적으로 ViewModel이 거대해질 수 밖에 없는 문제가 생긴다.
-데이터 바인딩을 쓸 수 없는 부분들이 많이 있기 때문에 결국 순환 이벤트 흐름이 생기게 된다.
-순환 이벤트 흐름 : View에서 사용자의 액션에 의해 변경된 상태가 ViewModel을 통해 데이터를 업데이트하고, 그 업데이트가 다시 View에 반영되면서 발생할 수 있따.이렇게 계속 반복되는 과정에서 데이터의 변경이 계속해서 View와 ViewModel 사이를 순환하게 되다가 갑작스럽게 예측하기 어려운 상태 변화 또는 불필요한 UI 갱신을 초래할 수 있다는 것을 말한다.
-View를 최대한 분리해서 각 View마다 ViewModel도 함께 분리한다.
-ViewModel의 비즈니스 로직 중에서 Domain Logic에 해당하는 부분은 부리해서 Domain 계층으로 이동시킨다.