이제 두 번째 Android 11 개발자 프리뷰를 사용할 수 있습니다. 테스트해 보고 의견을 공유하세요.

아키텍처 구성요소에 레이아웃 뷰 결합

AndroidX 라이브러리에는 성능이 뛰어나고 테스트와 유지관리가 쉬운 앱을 디자인하는 데 사용할 수 있는 아키텍처 구성요소가 포함되어 있습니다. 데이터 결합 라이브러리는 아키텍처 구성요소와 원활하게 연동하여 UI 개발을 더욱 단순화합니다. 앱의 레이아웃은 이미 UI 컨트롤러 수명 주기를 관리하고 데이터의 변경을 알리도록 돕는 아키텍처 구성요소의 데이터에 결합할 수 있습니다.

이 페이지에서는 앱에 아키텍처 구성요소를 통합하여 데이터 결합 라이브러리 사용의 이점을 더 강화하는 방법을 보여줍니다.

LiveData를 사용하여 UI에 데이터 변경 알림

LiveData 객체를 데이터 결합 소스로 사용하여 데이터 변경을 UI에 자동으로 알릴 수 있습니다. 이 아키텍처 구성요소에 관한 자세한 내용은 LiveData 개요를 참조하세요.

식별 가능한 필드와 같이 Observable을 구현하는 객체와 달리 LiveData 객체는 데이터 변경을 구독하는 관찰자의 수명 주기를 알고 있습니다. 이 수명 주기를 알면 LiveData 사용의 이점에 설명된 많은 이점을 활용할 수 있습니다. Android 스튜디오 버전 3.1 이상에서는 데이터 결합 코드에서 식별 가능한 필드LiveData 객체로 바꿀 수 있습니다.

결합 클래스와 함께 LiveData 객체를 사용하려면 수명 주기 소유자를 지정하여 LiveData 객체의 범위를 정의해야 합니다. 다음 예에서는 결합 클래스를 인스턴스화한 후 활동을 수명 주기 소유자로 지정합니다.

Kotlin

    class ViewModelActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            // Inflate view and obtain an instance of the binding class.
            val binding: UserBinding = DataBindingUtil.setContentView(this, R.layout.user)

            // Specify the current activity as the lifecycle owner.
            binding.setLifecycleOwner(this)
        }
    }
    

자바

    class ViewModelActivity extends AppCompatActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            // Inflate view and obtain an instance of the binding class.
            UserBinding binding = DataBindingUtil.setContentView(this, R.layout.user);

            // Specify the current activity as the lifecycle owner.
            binding.setLifecycleOwner(this);
        }
    }
    

ViewModel을 사용하여 UI 관련 데이터 관리에 설명된 대로 ViewModel 구성요소를 사용하여 데이터를 레이아웃에 결합할 수 있습니다. ViewModel 구성요소에서 LiveData 객체를 사용하여 데이터를 변환하거나 여러 데이터 소스를 병합할 수 있습니다. 다음 예는 ViewModel에서 데이터를 변환하는 방법을 보여줍니다.

Kotlin

    class ScheduleViewModel : ViewModel() {
        val userName: LiveData

        init {
            val result = Repository.userName
            userName = Transformations.map(result) { result -> result.value }
        }
    }
    

자바

    class ScheduleViewModel extends ViewModel {
        LiveData username;

        public ScheduleViewModel() {
            String result = Repository.userName;
            userName = Transformations.map(result, result -> result.value);
        }
    }
    

ViewModel을 사용하여 UI 관련 데이터 관리

데이터 결합 라이브러리는 ViewModel 구성요소와 원활하게 연동합니다. 이 구성요소는 레이아웃이 관찰하고 변경사항에 반응하는 데이터를 노출합니다. 데이터 결합 라이브러리와 함께 ViewModel 구성요소를 사용하면 UI 로직을 레이아웃에서 구성요소로 쉽게 이동할 수 있으므로 테스트하기가 더 쉽습니다. 데이터 결합 라이브러리를 사용하면 필요할 때 뷰를 데이터 소스에 결합하고 데이터 소스에서 결합 해제할 수 있습니다. 데이터 결합 라이브러리를 사용하는 그 밖의 작업은 대부분 적절한 데이터를 노출하고 있는지 확인하는 것입니다. 이 아키텍처 구성요소에 관한 자세한 내용은 ViewModel 개요를 참조하세요.

데이터 결합 라이브러리와 함께 ViewModel 구성요소를 사용하려면 ViewModel 클래스에서 상속받는 구성요소를 인스턴스화하고 결합 클래스의 인스턴스를 가져와 결합 클래스의 속성에 ViewModel 구성요소를 할당해야 합니다. 다음 예는 라이브러리와 함께 구성요소를 사용하는 방법을 보여줍니다.

Kotlin

    class ViewModelActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            // Obtain the ViewModel component.
            UserModel userModel = ViewModelProviders.of(getActivity())
                                                      .get(UserModel.class)

            // Inflate view and obtain an instance of the binding class.
            val binding: UserBinding = DataBindingUtil.setContentView(this, R.layout.user)

            // Assign the component to a property in the binding class.
            binding.viewmodel = userModel
        }
    }
    

자바

    class ViewModelActivity extends AppCompatActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            // Obtain the ViewModel component.
            UserModel userModel = ViewModelProviders.of(getActivity())
                                                      .get(UserModel.class);

            // Inflate view and obtain an instance of the binding class.
            UserBinding binding = DataBindingUtil.setContentView(this, R.layout.user);

            // Assign the component to a property in the binding class.
            binding.viewmodel = userModel;
        }
    }
    

다음 예에서와 같이 레이아웃에서 결합 표현식을 사용하여 적절한 뷰에 ViewModel 구성요소의 속성 및 메서드를 할당합니다.

<CheckBox
        android:id="@+id/rememberMeCheckBox"
        android:checked="@{viewmodel.rememberMe}"
        android:onCheckedChanged="@{() -> viewmodel.rememberMeChanged()}" />
    

결합 어댑터를 더 세밀하게 제어하기 위해 관찰 가능한 ViewModel 사용

Observable을 구현하는 ViewModel 구성요소를 사용하면 LiveData 객체를 사용하는 방식과 유사하게 데이터 변경을 다른 앱 구성요소에 알릴 수 있습니다.

LiveData의 수명 주기 관리 기능이 손실되었더라도 LiveData 객체를 사용하는 것보다 Observable 인터페이스를 구현하는 ViewModel 구성요소를 사용하는 것이 더 좋은 상황도 있습니다. Observable을 구현하는 ViewModel 구성요소를 사용하면 앱의 결합 어댑터를 더 세밀하게 제어할 수 있습니다. 예를 들어 이 패턴을 사용하면 데이터가 변경될 때 알림을 더 세밀하게 제어할 수 있으며 맞춤 메서드를 지정하여 양방향 데이터 결합의 속성 값을 설정할 수도 있습니다.

관찰 가능한 ViewModel 구성요소를 구현하려면 ViewModel 클래스에서 상속받고 Observable 인터페이스를 구현하는 클래스를 생성해야 합니다. 관찰자가 addOnPropertyChangedCallback()removeOnPropertyChangedCallback() 메서드를 사용하여 알림을 구독하거나 구독 취소할 때 맞춤 로직을 제공할 수 있습니다. 또한 notifyPropertyChanged() 메서드에서 속성이 변경될 때 실행되는 맞춤 로직을 제공할 수도 있습니다. 다음 코드 예는 관찰 가능한 ViewModel을 구현하는 방법을 보여줍니다.

Kotlin

    /**
     * A ViewModel that is also an Observable,
     * to be used with the Data Binding Library.
     */
    open class ObservableViewModel : ViewModel(), Observable {
        private val callbacks: PropertyChangeRegistry = PropertyChangeRegistry()

        override fun addOnPropertyChangedCallback(
                callback: Observable.OnPropertyChangedCallback) {
            callbacks.add(callback)
        }

        override fun removeOnPropertyChangedCallback(
                callback: Observable.OnPropertyChangedCallback) {
            callbacks.remove(callback)
        }

        /**
         * Notifies observers that all properties of this instance have changed.
         */
        fun notifyChange() {
            callbacks.notifyCallbacks(this, 0, null)
        }

        /**
         * Notifies observers that a specific property has changed. The getter for the
         * property that changes should be marked with the @Bindable annotation to
         * generate a field in the BR class to be used as the fieldId parameter.
         *
         * @param fieldId The generated BR id for the Bindable field.
         */
        fun notifyPropertyChanged(fieldId: Int) {
            callbacks.notifyCallbacks(this, fieldId, null)
        }
    }
    

자바

    /**
     * A ViewModel that is also an Observable,
     * to be used with the Data Binding Library.
     */
    class ObservableViewModel extends ViewModel implements Observable {
        private PropertyChangeRegistry callbacks = new PropertyChangeRegistry();

        @Override
        protected void addOnPropertyChangedCallback(
                Observable.OnPropertyChangedCallback callback) {
            callbacks.add(callback);
        }

        @Override
        protected void removeOnPropertyChangedCallback(
                Observable.OnPropertyChangedCallback callback) {
            callbacks.remove(callback);
        }

        /**
         * Notifies observers that all properties of this instance have changed.
         */
        void notifyChange() {
            callbacks.notifyCallbacks(this, 0, null);
        }

        /**
         * Notifies observers that a specific property has changed. The getter for the
         * property that changes should be marked with the @Bindable annotation to
         * generate a field in the BR class to be used as the fieldId parameter.
         *
         * @param fieldId The generated BR id for the Bindable field.
         */
        void notifyPropertyChanged(int fieldId) {
            callbacks.notifyCallbacks(this, fieldId, null);
        }
    }
    

추가 리소스

데이터 결합에 관해 자세히 알아보려면 다음 추가 리소스를 참조하세요.

샘플

Codelab

블로그 게시물