ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [AAC] DataBinding -3 <variable>에 뷰모델 변수
    Android/ArchitectureComponent 2021. 9. 14. 16:42

    이전 포스팅

    2021.09.11 - [Android/DataBinding] - [Android] DataBinding 2 - generated binding class

     

    데이터 바인딩과 ViewModel, LiveData를 같이 활용해야 하는데 

    데이터 바인딩과 ViewModel 둘을 활용하다가 막힌 점에 대해서

     

    바인딩 레이아웃

    MyViewModel타입 myViewModel변수

     

    layout expression으로 viewModel의 testString값을 텍스트 속성으로 설정

     

    MainActivity

     

    MyViewModel

     

    이 상태에서 TextView가 다른 적절한 String으로 업데이트 되어야 할때

    다음과 같이 하면 변경이 될까?

    myViewModel.testString="변경이 될까"

    onCreate, onStart에서는 뷰모델이 바뀌면 자동으로 바뀌었지만 버튼을 달아 리스너에 등록해놓은 경우 변경되지 않는다.

    여튼 변경이 안된다. 간단한 primitive타입이나 간단한 class는 새 객체를 대입하면 변경이 되긴한다.

    아마도 내부적으로 Observable한 필드로 저장이 되는 것같다.

     

    바인딩.varStr= "값 설정"
    바인딩.varStr= "다시 값 설정"

    varStr변수에 새로운 객체가 대입될때는 변경된다.

     

    val testUser: User = User("첫번째는 ui변경됨")
    binding.user = testUser
    testUser.name = "이런경우 ui변경안됨"
    
    val testUser2: User = User("새로운 객체로 갈아넣으면 변경됨")
    binding.user = testUser2

    바인딩 데이터 변수 user에 인스턴스를 대입할때면 TextView의 ui는 자동으로 변경되지만

    대입된 상태에서 user인스턴스의 String인 name을 바꾸면 TextView의 ui는 변경이 되지 않는다.

     

    이를 통해 바인딩 변수는 옵져빙 되고있는 변수로 취급된다는걸 확인했다.


    이렇게 ViewModel에서 값을 변경해도 ui가 변경되지 않기 때문에 DataBinding은 Observable한 필드와 객체들을 지원한다. 

    import androidx.databinding.ObservableField 등등에 해당. 

     

    그러나 DataBinding이 LiveData를 지원하기 때문에 LiveData를 사용하기를 권장하고 있다.

    (데이터바인딩의 Observable은 라이프사이클을 모르고 LiveData는 lifecycle aware컴포넌트이기 떄문, 메모리 릭 문제 완화)

     

    이외에도 ObservableField<String> 등등 많다. 이러한 것이 있다는 것만 알아두고 LiveData를 더 공부하려고 한다. 

    class MyViewModel : ViewModel() {
        var observeString: ObservableField<String> = ObservableField<String>("")
    
    }

     

    버튼을 하나 달아서 리스너를 셋팅해놨다. 테스트를 위해 아키텍쳐 생각 안하고 코드안에서 리스너를 설정하였다.

    class BindingAndViewModel : AppCompatActivity() {
        var count:Int=1
        val myViewModel: MyViewModel by lazy { ViewModelProvider(this).get(MyViewModel::class.java) }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            val binding: ActivityBindingAndViewModelBinding =
                DataBindingUtil.setContentView(this, R.layout.activity_binding_and_view_model)
    
            ViewModelProvider(this).get(MyViewModel::class.java)
    
            binding.myViewModel = myViewModel
            binding.button.setOnClickListener(View.OnClickListener() {
                myViewModel.observeString.set(count.toString())
                count++
            })
        }
    
        fun printLog(str: String) {
            Log.d("DataBinding", str)
        }
    }

    ViewModel의 관찰가능한 String객체이기 때문에  set(스트링)으로 업데이트할때마다 ui가 변경이 잘된다.


    데이터바인딩 패키지의 ObservableField, ObservableInt등등을 사용하지 않고 LiveData를 사용한 경우

    class MyViewModel : ViewModel() {
        var liveString = MutableLiveData<String>("test")
    }

    binding.myViewModel = myViewModel
    binding.lifecycleOwner = this
    binding.button.setOnClickListener(View.OnClickListener() {
         myViewModel.liveString.setValue(count.toString())
         count++
    })
    class BindingAndViewModel : AppCompatActivity() {
        var count: Int = 1
        val myViewModel: MyViewModel by lazy { ViewModelProvider(this).get(MyViewModel::class.java) }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            val binding: ActivityBindingAndViewModelBinding =
                DataBindingUtil.setContentView(this, R.layout.activity_binding_and_view_model)
    
            ViewModelProvider(this).get(MyViewModel::class.java)
    
            binding.myViewModel = myViewModel
            binding.lifecycleOwner = this //안쓰면 데이터 변경이 통지가 안됨
            binding.button.setOnClickListener(View.OnClickListener() {
                myViewModel.liveString.setValue(count.toString())
                count++
            })
        }
    
        fun printLog(str: String) {
            Log.d("DataBinding", str)
        }
    }

    ViewDataBinding.setLifecycleOwner

     

    Sets the LifecycleOwner that should be used for observing changes of LiveData in this binding. If a LiveData is in one of the binding expressions and no LifecycleOwner is set, the LiveData will not be observed and updates to it will not be propagated to the UI.

     

    LiveData를 통지받기 위해 바인딩클래스의 라이프사이클 오너 설정을 해야한다.

     

     

    댓글

Designed by Tistory.