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

AndroidX 라이브러리에는 강력하고 테스트와 유지관리가 쉬운 앱을 디자인하는 데 사용할 수 있는 아키텍처 구성요소가 포함되어 있습니다. 데이터 결합 라이브러리는 아키텍처 구성요소와 원활하게 연동하여 UI 개발을 더욱 간소화합니다. 앱의 레이아웃은 아키텍처 구성요소의 데이터에 결합할 수 있습니다. 아키텍처 구성요소의 데이터는 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)
    }
}

Java

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 구성요소를 사용하여 데이터를 레이아웃에 결합할 수 있습니다. ViewModel 구성요소에서 LiveData 객체를 사용하여 데이터를 변환하거나 여러 데이터 소스를 병합할 수 있습니다. 다음 예는 ViewModel의 데이터를 변환하는 방법을 보여줍니다.

Kotlin

class ScheduleViewModel : ViewModel() {
    val userName: LiveData

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

Java

class ScheduleViewModel extends ViewModel {
    LiveData username;

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

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

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

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

Kotlin

class ViewModelActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        // Obtain the ViewModel component.
        val userModel: UserModel by viewModels()

        // 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
    }
}

Java

class ViewModelActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // Obtain the ViewModel component.
        UserModel userModel = new ViewModelProvider(this).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 must 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)
    }
}

Java

/**
 * 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 must 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);
    }
}

추가 리소스

데이터 결합에 관한 자세한 내용은 다음 추가 리소스를 참고하세요.