简体   繁体   中英

Live Data is getting called multiple times?

I'm using Android Architecture Components in my App. In My Login Activty, I'm showing a Dialog when the login is failed!

Due to Live Data, the dialog has been showing over 3 times. I added some logs & discovered that the livedata is called multiple times.

How can I Fix this Issue ?

ACTIVITY

mViewModel.authenticate(token, binding.inputPassword.getText().toString()).observe(LoginActivity.this, apiResponse -> {
    progress.dismiss();
    if (apiResponse != null) {
        if (apiResponse.getError() != null) {
            Log.e("Login", "Network Failure");
        } else {
            if (apiResponse.getAuthuser().getStatus().equals("VALID")) {
                PrefUtils.saveUserToPrefs(LoginActivity.this, apiResponse.getAuthuser());
                finish();
            } else if (apiResponse.getAuthuser().getStatus().equals("INVALID")) {
                Log.e("LOGIN Issue ", "Showing Dialog" + apiResponse.getAuthuser().getStatus());
                loginFailure();
            }
        } 
    }
});

ViewModel

class LoginActivityViewModel extends ViewModel {

    private final FarmerRepository farmerRepository;
    private MediatorLiveData<ApiResponse> mApiResponse;

    LoginActivityViewModel(FarmerRepository repository) {
        mApiResponse = new MediatorLiveData<>();
        farmerRepository = repository;
    }

    MediatorLiveData<ApiResponse> authenticate(String encryptedMobile, String pwd) {
        mApiResponse.addSource(
                farmerRepository.authenticate(encryptedMobile, pwd),
                apiResponse -> mApiResponse.setValue(apiResponse)
        );
        return mApiResponse;
    }
}

LOGCAT

11-01 00:13:31.265 24386-24386 E/LOGIN Issue: Showing DialogINVALID

11-01 00:13:31.312 24386-24386 E/LOGIN Issue: Showing DialogINVALID
11-01 00:13:37.034 24386-24386 E/LOGIN Issue: Showing DialogINVALID

11-01 00:13:38.196 24386-24386 E/LOGIN Issue: Showing DialogINVALID
11-01 00:13:38.234 24386-24386 E/LOGIN Issue: Showing DialogINVALID
11-01 00:13:38.273 24386-24386 E/LOGIN Issue: Showing DialogINVALID

UPDATE

After using SingleLiveEvent. It is not being observed. Can you tell me what is wrong with the code ?

Updated ViewModel

class LoginActivityViewModel extends ViewModel {

    private final FarmerRepository farmerRepository;
    private MediatorLiveData<ApiResponse> mApiResponse;
private SingleLiveEvent<ApiResponse> mMsgUpdate;

    LoginActivityViewModel(FarmerRepository repository) {
        mApiResponse = new MediatorLiveData<>();
        farmerRepository = repository;
    mMsgUpdate = new SingleLiveEvent<>();
    }

    SingleLiveEvent<ApiResponse> authenticate(String encryptedMobile, String pwd) {
        mApiResponse.addSource(
                farmerRepository.authenticate(encryptedMobile, pwd),
                apiResponse -> mMsgUpdate.setValue(apiResponse)
        );
        return mMsgUpdate;
    }
}

The role of the ViewModel is to represent the current state of the view. LiveData adds the ability to observe state changes. You are treating your LiveData object as a way to carry the response back upon a call to authenticate. Instead, your authenticate method should simply take the credentials as parameters, decide whether or not to log the person in, and if you do, update the LiveData ViewModel to reflect that the person is logged in, then observers will get this and most likely dismiss this view and show whatever other parts of the authenticated state you want to show (eg LoggedInUsername).

So in summary:

  • make a class called CurrentAuthenticatedSession or something, with for instance a username field, and have that be null to begin with
  • when the authentication call is made, verify look up the user info
  • if it's current update the LiveData instance of your CurrentAuthenticatedSession
  • have the 'currentlyLoggedInUser' field be listening for updates to this object
  • set the text of that control to the value of the field username

That's one way. Because a login screen is transient, observers of state updates may be seen as superfluous. But that's how the ViewModel/LiveData mechanism works.

My answer is not a solution to this question description but rather to question title. Just title.

Originally answered here

If your observer for a LiveData<*> is getting called multiple times then it means you are calling livedata.observe(...) multiple times. This happened to me as I was doing livedata.observe(...) in a method and was calling this method whenever user does some action thus observing liveData again. To solve this I moved livedata.observe(...) to onCreate() lifecycle method.

What was the scenario? The App has a color swatch. When user selects a color I had to make API call to fetch Product Images for that color. So was making API call and was observing livedata in onColorChanged() . When user selects a new color, onColorChanged() would be called again thus observing for livedata changes again.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM