Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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;
    }
}
like image 608
user3467240 Avatar asked Oct 28 '17 18:10

user3467240


People also ask

How do I stop observing live data?

You should manually call removeObserver(Observer) to stop observing this LiveData. While LiveData has one of such observers, it will be considered as active. If the observer was already added with an owner to this LiveData, LiveData throws an IllegalArgumentException .

Why LiveData Observer is being triggered twice?

Since we are using switchmap in viewmodel and the livedata was set again the observer in fragment A was getting triggered twice. To fix this all i had to do was check if livedata had the same value that is being set now to avoid making network calls and triggering livedata in fragment A twice.

What do you call live data?

LiveData overview Part of Android Jetpack. LiveData is an observable data holder class. Unlike a regular observable, LiveData is lifecycle-aware, meaning it respects the lifecycle of other app components, such as activities, fragments, or services.


2 Answers

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 (e.g. 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.

like image 96
Rob Avatar answered Oct 08 '22 01:10

Rob


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.

like image 41
Ramakrishna Joshi Avatar answered Oct 08 '22 02:10

Ramakrishna Joshi