MutableLiveData에서 setValue ()와 postValue ()의 차이점


105

의 값을 변경하는 방법에는 두 가지가 있습니다 MutableLiveData. 그러나 사이의 차이가 무엇 setValue()& postValue()인은 MutableLiveData.

동일한 문서를 찾을 수 없습니다.

다음은 MutableLiveDataAndroid 클래스 입니다.

package android.arch.lifecycle;

/**
 * {@link LiveData} which publicly exposes {@link #setValue(T)} and {@link #postValue(T)} method.
 *
 * @param <T> The type of data hold by this instance
 */
@SuppressWarnings("WeakerAccess")
public class MutableLiveData<T> extends LiveData<T> {
    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}

답변:


178

문서를 기반으로 :

setValue () :

값을 설정합니다. 활성 옵저버가 있으면 값이 그들에게 전달됩니다. 이 메서드는 주 스레드에서 호출해야합니다.

postValue () :

주어진 값을 설정하기 위해 작업을 메인 스레드에 게시합니다. 주 스레드가 게시 된 작업을 실행하기 전에이 메서드를 여러 번 호출하면 마지막 값만 전달됩니다.

요약하면 주요 차이점은 다음과 같습니다.

setValue()메서드는 메인 스레드에서 호출되어야합니다. 그러나 백그라운드 스레드에서 값을 설정해야하는 경우 postValue()사용해야합니다.


"마지막 값만 전달됩니다". 코드를 읽어 보면 확신 할 수 없습니다. 따라서 첫 번째 스레드가 postValue () 내부의 동기화 된 내부 블록에 도달하려고하면 잠재적으로 다른 값을 게시하는 스레드 2에 다음 CPU 창이 주어질 수 있습니다. 그런 다음 스레드 2는 동기화 된 블록을 완료 할 수 있으며 스케줄러는 첫 번째 스레드에 자체적으로 실행할 창을 제공합니다. 이제 스레드 2가 이미 작성한 것을 덮어 씁니다. 이게 가능해?
stdout

96

위의 모든 답변이 정확합니다. 그러나 한 가지 더 중요한 차이점이 있습니다. postValue()관찰자가없는 필드 를 호출 한 후를 호출 getValue()하면에서 설정 한 값을받지 못합니다 postValue(). 따라서 관찰자없이 백그라운드 스레드에서 작업하는 경우주의하십시오.


3
트리플 찬성 수 있기를 바랍니다! 이를 바탕으로 setValue()가능한 한 사용 하는 것이 가장 좋으며 필요할 때만 'postValue ()'를 조심스럽게 사용하십시오. 감사합니다
jungledev

1
아니요, 여기에 "최상의"방법은 없습니다. 백그라운드 스레드에서 LiveData로 작업하는 경우 postValue를 사용해야합니다. 또한 최신 버전의 수명주기 구성 요소에서 수정되었습니다.
w201

"또한 최신 버전의 수명주기 구성 요소에서 수정되었습니다 ... 아마도." 이것에 대한 더 많은 정보가 있습니까? 감사합니다
Chris Nevill

1
나는 몇 가지 테스트를했고 lib의 마지막 버전에서는 모든 것이 제대로 작동하는 것 같습니다.
w201

위의 코드를 구체적으로 보여줄 수 있습니까? ViewModel에서 noObserveLiveData.postValue("sample"), In Activity 처럼 구현 한 경우 getValue를 다음과 같이 사용할 때 viewModel.noObserveLiveData.getValuepostValue () ( "sample")에서 설정 한 값이 아닙니까?
kwmt

14

setValue()호출자 스레드에서 직접 호출되어 관찰자에게 동 기적으로 알리고 LiveData값을 즉시 변경 합니다. MainThread에서만 호출 할 수 있습니다.
postValue()이와 같은 내부에서 사용 new Handler(Looper.mainLooper()).post(() -> setValue())하므로 MainThread에서 실행 setValue됩니다 Handler. 모든 스레드에서 호출 할 수 있습니다.


11

setValue()

값을 설정합니다. 활성 옵저버가 있으면 값이 그들에게 전달됩니다.

이 메서드는 주 스레드에서 호출해야합니다 .

postValue

백그라운드 스레드에서 값을 설정해야하는 경우 다음을 사용할 수 있습니다. postValue(Object)

주어진 값을 설정하기 위해 작업을 메인 스레드에 게시합니다.

주 스레드가 게시 된 작업을 실행하기 전에이 메서드를 여러 번 호출하면 마지막 값만 전달됩니다.


5

이것은 위의 문제에 대한 직접적인 대답이 아닙니다. Sagarw201 의 답변 은 굉장합니다. 그러나 MutableLiveData에 대한 ViewModels에서 사용하는 간단한 경험 법칙은 다음과 같습니다.

private boolean isMainThread() {
    return Looper.myLooper() == Looper.getMainLooper();
}

private MutableLiveData<Boolean> mutVal = new MutableLiveData<>(false);
public LiveData<Boolean> getMutVal() { return this.mutVal;  }
public void setMutVal(boolean val) {
    if (isMainThread()) mutVal.setValue(val);
    else mutVal.postValue(val);
}

mutVal원하는 값으로 바꿉니다 .


좋아, 좋아. Kotlin에서는 스마트 업데이트를 캡슐화하는 확장 프로그램을 만들었으므로 앱 전체의 수많은 값 업데이트가 일관된 단일 호출이됩니다.
19Craig

4

setValue()메서드는 메인 스레드에서 호출되어야합니다. 백그라운드 스레드에서 값을 설정해야하는 경우 postValue().

여기 .


0

우리 앱에서는 활동 / 화면의 여러 뷰에 대한 데이터가 포함 된 단일 LiveData를 사용했습니다. 기본적으로 N 개의 뷰에 대한 데이터 세트가 없습니다. 이것은 postData가 설계된 방식 때문에 우리에게 약간의 문제가되었습니다. 그리고 어떤 뷰를 업데이트해야하는지에 대한 뷰를 전달하는 LD의 상태 객체가 있습니다.

그래서 LD는 다음과 같습니다.

LD {
   state (view_1, view_2, view_3 …),
   model_that_contains_data_of_all_views
}

하나의 이벤트가 발생할 때 업데이트해야하는 두 개의 뷰 (view_1 및 view_2)가 있습니다. 즉, 이벤트가 발생하면 동시에 알림을 받아야합니다. 그래서 저는 다음과 같이 전화했습니다.

postData(LD(view_1, data))
postData(LD(view_2, data)

이것은 우리가 알고있는 이유로 작동하지 않습니다.

내가 이해 한 것은 기본적으로 하나의 LD가 하나의 뷰만 나타내야한다는 것입니다. 그러면 postData ()를 연속으로 두 번 호출 할 가능성이 없습니다. 전화를 걸어도 postData가 처리하는 방식은 예상 할 수있는 것입니다 (보기에 최신 데이터 표시). 모든 것이 제자리에 있습니다.

하나의 LD-> 하나의보기. 완전한

하나의 LD-> 다중보기 이상한 동작이있을 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.