반응형

이번 포스팅은 App Architecture 가이드 두 번째 포스팅입니다.

예제를 통해 좀 더 자세히 알아보도록 하겠습니다.


사용자 인터페이스 시작

UI는 fragment UserProfileFragment와 관련 레이아웃 파일 user_profile_layout.xml로 구성됩니다.

UI를 만들려면 데이터 모델에 다음 데이터 요소가 있어야 합니다.

▶ 사용자 ID: 사용자의 식별자입니다. fragment 인수를 사용하여 이 정보를 fragment에 전달하는 것이 좋습니다. Android OS에서 프로세스를 제거해도 이 정보가 유지되므로, 앱을 다시 시작할 때 ID를 사용할 수 있습니다.

▶ 사용자 개체: 사용자에 관한 세부정보를 보유하는 데이터 클래스입니다.

이 정보를 유지하기 위해 ViewModel 아키텍처 구성요소를 기반으로 하는 UserProfileViewModel을 사용합니다.

ViewModel 개체는 fragment나 activity 같은 특정 UI 구성요소에 대한 데이터를 제공하고 Model과 커뮤니케이션하기 위한 데이터 처리 비즈니스 로직을 포함합니다. 예를 들어 ViewModel은 데이터를 로드하기 위해 다른 구성요소를 호출하고 사용자 요청을 전달하여 데이터를 수정할 수 있습니다. ViewModel은 UI 구성요소에 관해 알지 못하므로 구성 변경(예: 기기 회전 시 activity 재생성)의 영향을 받지 않습니다.

지금까지 다음 파일을 정의했습니다.

▶ user_profile.xml: 화면의 UI 레이아웃 정의

▶ UserProfileFragment: 데이터를 표시하는 UI 컨트롤러

▶ UserProfileViewModelUserProfileFragment에서 볼 수 있도록 데이터를 준비하고 사용자 상호작용에 반응하는 클래스

다음 소스 코드는 이러한 파일의 시작 콘텐츠를 보여줍니다. 

편의를 위해 레이아웃 파일은 생략합니다.

UserProfileViewModel

class UserProfileViewModel:ViewModel(){

val userId :String= TODO() val user :User= TODO() }

UserProfileFragment

class UserProfileFragment:Fragment(){

override fun onCreateView(inflater:LayoutInflater, container:ViewGroup?, savedInstanceState:Bundle?):View{
return inflater.inflate(R.layout.main_fragment, container,false)
}
}

user를 가져오려면 ViewModel에서 Fragment 인수에 액세스해야 합니다. Fragment에서 인수를 전달할 수도 있고, 더 나은 방법으로 SavedState 모듈을 사용해 ViewModel에서 직접 인수를 읽을 수 있습니다.

참고: SavedStateHandle을 사용하면 ViewModel에서 관련 Fragment 또는 Activity의 저장된 상태와 인수에 액세스할 수 있습니다.


// UserProfileViewModel

class UserProfileViewModel( savedStateHandle:SavedStateHandle ):ViewModel(){
val userId :String= savedStateHandle["uid"]?: throwIllegalArgumentException("missing user id") val user :User= TODO()
}

// UserProfileFragment
privateval viewModel:UserProfileViewModel by viewModels(factoryProducer ={SavedStateVMFactory(this)}        ... )

이제 user 개체가 확보되면 Fragment에 알려야 합니다. 여기에서 LiveData 아키텍처 구성요소가 사용됩니다.

LiveData는 식별 가능한 데이터 홀더입니다. 앱의 다른 구성요소에서는 이 홀더를 사용하여 상호 간에 명시적이고 엄격한 종속성 경로를 만들지 않고도 개체 변경사항을 모니터링할 수 있습니다. 또한 LiveData 구성요소는 activity, fragment, 서비스와 같은 앱 구성요소의 수명 주기 상태를 고려하고, 개체 유출과 과도한 메모리 소비를 방지하기 위한 정리 로직을 포함합니다.

참고: RxJava와 같은 라이브러리를 이미 사용하고 있다면 LiveData 대신 계속 사용해도 됩니다. 그러나 이러한 라이브러리와 방법을 사용하는 경우 앱의 수명 주기를 올바르게 처리해야 합니다. 특히 관련 LifecycleOwner가 중지되면 데이터 스트림이 일시중지되고, 관련 LifecycleOwner가 제거되면 이러한 스트림이 제거되도록 해야 합니다. android.arch.lifecycle:reactivestreams 아티팩트를 추가하여 LiveData를 다른 반응형 스트림 라이브러리(예: RxJava2)와 함께 사용할 수도 있습니다.

LiveData 구성요소를 앱에 통합하기 위해 UserProfileViewModel의 필드 유형을 LiveData<User>로 변경합니다. 이제 데이터가 업데이트되면 UserProfileFragment에 정보가 전달됩니다. 또한 이 LiveData 필드는 수명 주기를 인식하기 때문에 더 이상 필요하지 않은 참조를 자동으로 정리합니다.

UserProfileViewModel

class UserProfileViewModel( savedStateHandle:SavedStateHandle):ViewModel(){

val userId :String= savedStateHandle["uid"]?: throw IllegalArgumentException("missing user id") val user :LiveData<User>= TODO()
}

이제 데이터를 관찰하고 UI를 업데이트하도록 UserProfileFragment를 수정합니다.

UserProfileFragment

override fun onViewCreated(view:View, savedInstanceState:Bundle?){ super.onViewCreated(view, savedInstanceState)
viewModel
.user.observe(viewLifecycleOwner){ // update UI } }

사용자 프로필 데이터가 업데이트될 때마다 onChanged() 콜백이 호출되고 UI가 새로고침됩니다.

반응형

+ Recent posts