Live Data에 대한 몇 가지 오해가 있습니다.

14700 단어 AndroidKotlin
(이하 AAC)에 포함된 LiveData의 샘플은 Kotlin으로 작성되었습니다.

LiveData란 무엇입니까?


Android Architecture Components은'라이프 사이클에 따라 자동으로 구독을 취소하는 알림 속성'입니다.
현대(이미 유행이 지났어?)사용자 인터페이스 모드에서 사용자 인터페이스에서 데이터의 변경을 감지하고 자신을 고칩니다.
즉, UI 측은'구독 데이터'코드를 써야 하지만,'구독 정지'코드를 고려해야 한다.그러나 Android의 Activity와 Fragment는 생명주기가 복잡하고 구독 관리도 힘들어 문제의 온상이 되기 쉽다.
LiveData는 AAC에 포함된 Lifecycle과 깊은 관계를 가지고 있으며 거의 자동으로 이'구독 취소'를 진행할 수 있습니다.

시도된 응용 프로그램


도대체 몇 명이 몇 번을 만들었는지를 보여주는 GitHub의 메모리 리스트다.
LiveData
주요 요소는 다음과 같습니다.
  • 의존도는 MainActivity->MainViewModel->GithubRepository->GithubService
  • MainViewModel은 사용자 이름과 저장소 목록을 LiveData로 게시합니다.그리고 로드 방법.
  • MainActivity는 EditText 또는 ListView를 MainViewModel의 LiveData와 데이터 바인딩(자제)
  • load가 호출될 때 MainView Model은 GithubRepository를 사용하여 저장소 목록을 비동기적으로 요청하고 가져올 수 있으면 LiveData를 업데이트합니다.
  • GithubRepository는 Retrofit만 사용합니다.사용자 인터페이스 스레드가 리셋되지 않도록 설정callbackExecutor.
  • coroutine(async/await), RxJava, DataBinding을 사용하지 않았습니다.가능한 한 LiveData의 간단한 지침만 사용합니다.
  • LiveData는 라이프 사이클과 결합하여 구독 관리를 하는 것으로 ViewModel에서 사용하는 것이 자연스럽습니다.구글의 샘플도 마찬가지다.

    Live Data가 오해한 것


    그렇다면 Live Data를 실제로 사용할 때 "진짜야..."라고 생각하는 부분이 몇 가지 있습니다. 제가 들어볼게요.

    "변경 알림" 이 아니라 "처짐" 입니다


    제가 기대하는 것은'DataBinding의 Observable Field처럼 사용할 수 있고 구독 관리가 쉽다'는 것입니다. 하지만 여기와 Observable Field는 결정적인 차이가 있습니다.
    값이 변경되면 ObservableField에서 알림을 보냅니다.
    값이 변경되지 않은 경우에도 LiveData는 설정 후 알림을 보냅니다.
    val observableFld = ObservableField<Int>()
    observableFld.set(5)
    observableFld.set(5)
    observableFld.set(5) // 最初の1回しか通知されない(=onChangedは呼ばれない)
    
    val liveData = MutableLiveData<Int>()
    liveData.postValue(5)
    liveData.postValue(5)
    liveData.postValue(5)// 3回とも通知される(=onChangedが呼ばれる)
    
    값이 변경되면 ViewModel에 있는 속성을 알려 주고 View 측면에서 해당 속성을 감지하고 업데이트합니다.
    상식이야, LiveData도 꼭 그렇게 될 거야, 그렇지만, 달라(onChanged...).
    이 일을 모르면 다음과 같은 위험이 있다.
  • 쓸모없는 화면 업데이트 발생
  • TwoWay 귀속을 고려하지 않고 무한 순환 중 사망
  • 후자는 이 샘플을 만드는 과정에서 체험한 것이다.
    "고려할 필요 없음"은 다음과 같이 화면의 EditText 및 ViewModel LiveData 의 TwoWay 바인딩을 실현합니다.
    // viewModel.user の TwoWay バインド
    // EditText -> LiveData
    editUserName.addTextChangedListener(object : TextWatcher {
        override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
            val userName = editUserName.text;
            viewModel.user.postValue(userName.toString())
        }
    
        override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { }
        override fun afterTextChanged(p0: Editable?) { }
    })
    
    // LiveData -> EditText
    viewModel.user.observe(this, Observer { userName ->
        editUserName.setTextKeepState(userName ?: "")
    })
    editUserName.setTextKeepState(viewModel.user?.value ?: "")
    
    이 코드는 처음editUserName.setTextKeepState을 터치로 TextWatcher를 진행합니다.onTextChanged 및 LiveData.observe 무한 반복.
    이번에는 Text Watcher입니다.onTextChanged에서 등가 검사를 하고 회피했지만 의외의 고장이 발생할 수 있습니다.

    setValue는 UI 스레드에서 호출되어야 합니다(postValue 사용).


    실제 LiveData 값을 설정할 수 있는 클래스 MutableLiveData<T>: setValue()postValue() 에는 두 가지 값 업데이트 방법이 있습니다.
    처음에는 setValue()만 알고 사용했지만 비 UI 스레드에서 (Retrofit의 리셋 스레드에서) setValue() 사용하면 Illegal은 드디어 Exception이 나온 셈이다.
    LiveData 코드를 추적할 때 다음 그림과 같이 UI 스레드가 맞는지 확인하고 예외를 발생합니다.
    음, Live Data의 set Value, 주 스레드에서 호출하지 않으면 잘못된 건가요?그것은 Observe 측(즉 View-Binding 측)에서 관리하는 것이다.ReactiveProperty. - 아미@ 하이델라 기다리기(@amay077)pic.twitter.com/jSkXT4LK8w
    하지만 그 뒤에도 2017년 11월 2일 씨도 postValue() 있어요!가르침을 청하다p>


    2017年11月3日는 UI 스레드에서 값을 업데이트하고 알림하는 방법입니다.p>
    모델 측면의 처리는 일반적으로 비동기식 즉 비UI 스레드를 전제로 하기 때문에 postVata 실제로는 사용할 수 없다p>
    그리고 LiveData는 UI 스레드에 강하게 의존하므로 ViewModel에서 반대편까지 사용하지 말아야 합니다.p>
    반대setValueLiveData는UI 스레드에서진행이 보장되므로특별히observe등을할 필요가 없습니다.p>

    ObservableField と併用不可?


    그렇다면 DataBinding은 runOnUiThread 의 기본 클래스 또는 BaseObservale 을 필요로 합니다.가령 AAC=ObservavleField를 기류로 사용하는 경우가 많기 때문에 전자는 실제로 사망한다.DataBinding을 사용하려면 ObservableField만 사용할 수 있습니다.하지만 ObservableField와 LiveData는 현재 아무런 관계가 없는 반이기 때문에


    • DataBinding을 원한다면 ObservableField
    • Lifecycle aware 코드를 쓰고 싶다면 LiveData

    를 구분해서 사용해야 합니다.비록 목적은 다르지만 늘 미묘하게 느껴진다p>

    2017/12/21 追記


    LiveData가 DataBinding을 지원합니다.즉, ViewModel 필요 없는 아이가 될 가능성p>



    You can now use a LiveData object as an observable field in data binding expressions.(계속)


    변경 알림이 아니라'값만 내려준다'는 LiveData가 데이터 귀속을 할 수 있는데 어떻게 될지 흥미롭습니다.계속 보도하도록 하겠습니다.p>

    Solutions?


    불평만으로는 해결할 수 없으니 현상황을 타개할 수 있는 방법을 모색해 보자.

    Kotlin이라면 확장 방법을 사용할 수 있으니 편리한 확장 방법을 만들어서 사용하면 되지 않을까요?p>

    「値が変わった時だけ」通知を行う LiveData の拡張メソッドを作る


    먼저, "LiveData는 값 변경과 무관하게 통지됨"에 관하여 값이 변경되었는지 확인하고, 변경되었을 때만 통지하는 확장 방법을 만들었습니다.p>
    fun <T> LiveData<T>.observeOnChanged(owner: LifecycleOwner, observer: Observer<T>) : Unit {
        var prev : T? = null
        this.observe(owner, Observer<T> {
            if (!(prev?.equals(it) ?: false)) {
                observer.onChanged(it)
            }
            prev = it
        })
    }
    
    // 使う方
    val liveData = MutableLiveData<Int>()
    
    liveData.observeOnChanged(owner, Observer {
        Log.d(TAG, "$it")
    });
    
    liveData.postValue(5)
    liveData.postValue(5)
    liveData.postValue(5)// 最初の1回しか onChanged は呼ばれない
    

    やっぱり Observable がイイ!


    LiveData의 구독 관리가 수월해지는 것은 좋지만mapswitchMap(flatMap かな) 등 최소한의 합성법만 있다는 점과 DataBinding의 병용이 번거로워 보인다는 점은 미묘하다p>

    ViewModel의 반대편(Usecase층과 Repository층)의 I/F는Observable<T>이거나 서로 변환하고 싶은 물건이라면 ViewModel도 사용하고 싶다Observable<T>p>
    그래서 저는 ObservableField, LiveData, RxJava를 좋은 느낌으로 함께 사용할 수 있는 방법을 생각해 봤습니다. 그래서 내일의 "Android Studio Release Updates: Android Studio 3.1 Canary 6 is now available에 적었습니다.p>

    좋은 웹페이지 즐겨찾기