簡體   English   中英

Android 實時數據 - 配置更改后觀察總是觸發

[英]Android live data - observe always fires after config change

我目前正在重構我的代碼以包含 ViewModel 和 android.arch 庫提供的 LiveData。 我有一個簡單的活動,它將更改密碼的請求發送到服務器並根據 HTTP 響應代碼進行操作。

為此,我創建了為數據擴展 ViewModel 的類和一個用於調用服務器的存儲庫類。 我的 ViewModel 類有一個 MutableLiveData 字段,我使用 .observe(...) 方法從我的活動中訂閱該字段。 問題是 .observe(...) 中的代碼在配置更改(即屏幕旋轉)后一直觸發,我不知道為什么。

以下是相應的 ViewModel、Repository 和 Activity 類的代碼:

更改密碼視圖模型

public class ChangePasswordViewModel extends ViewModel{

    private MutableLiveData<Integer> responseCode;
    private PasswordChangeRepository passwordChangeRepository;

    public ChangePasswordViewModel() {
        responseCode = new MutableLiveData<>();
        passwordChangeRepository = new PasswordChangeRepositoryImpl();
    }

    public MutableLiveData<Integer> responseCodeLiveData() {
        return responseCode;
    }

    public void sendChangePasswordRequest(String newPassword){
        passwordChangeRepository.changePassword(newPassword,     passChangeCallback());
    }

    // Callback that fires after server sends a response
    private Callback passChangeCallback(){
        ...
        responseCode.postValue(serverResponse)
        ...
}

密碼更改存儲庫

public class PasswordChangeRepositoryImpl {

    public void changePassword(String newPassword, Callback<Void> callback){
        //Sending new password to server and processing response in callback
        ServerCalls.changePassword(newPassword, callback);
    }
}

活動

public class ChangePasswordActivity extends AppCompatActivity{
...
    private void init(){
        //Getting appropriate view model
        passwordViewModel = ViewModelProviders.of(this).get(ChangePasswordViewModel.class);

        // Starting to observe LiveData
        passwordViewModel.getResponseCode().observe(this, responseCode -> {
           Log.info("Server response is " + responseCode);
        });

        //Sending new password to server
        buttonPassChange.setOnClickListener(view ->
            passwordViewModel.sendChangePasswordRequest("newPass")
        );
    }
...
}

問題是我第一次使用 sendChangePasswordRequest(...) 向服務器發送請求后觀察活動中的代碼

passwordViewModel.getResponseCode().observe(this, responseCode -> {
           Log.info("Server response is " + responseCode);
        });

每次旋轉屏幕后都會觸發。 為什么會這樣? 自上次服務器調用以來 MutableLiveData responseCode 的值尚未更新,那么如果實時數據沒有更改,為什么 .observe() 會觸發?

正如您在文檔中看到的那樣,這是一種預期的行為:

觀察(LifecycleOwner 所有者,觀察者觀察者)在給定所有者的生命周期內將給定觀察者添加到觀察者列表中。 事件在主線程上調度。 如果 LiveData 已經有數據集,它將被傳遞給觀察者。

如果您想觀察視圖狀態的變化,那么您應該創建並觀察視圖狀態而不是網絡請求,谷歌已經為此類情況提供了一個示例

除了上面的回答,了解使用 ViewModel 和 LiveData 觀察者的場景很重要,只觀察一次,本文解釋了它們並展示了一種輕松處理它的方法: Working with LiveData and Events

我使用了 MutableSharedFlow 而不是 MutableLiveData,並解決了與您相同的問題。

你可以試試這個:

    private val responseCode = MutableSharedFlow<Int>()
    ...
    fun passChangeCallback() {
        viewModelScope.launch {
        responseCode.emit(serverResponse)
    }

因為 MutableSharedFlow 不會重放已經由 defalut 發出的值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM