Search code examples
androidmvvmviewmodelandroid-livedatamutablelivedata

ViewModel and LiveData are not deleted after the application is closed. Why?


I just started learning android development and I had a problem, I’m happy to get any help.

When I click the "User exists?" Button, a request is sent to the server and the server returns either a user or null (in my case, always null, because no users are created on the server).

After clicking on the button in the observer, the following is displayed in the log:

UserResult onChanged

UserResult NOT NULL

UserResult false null

That is, everything works perfectly.

When I close the application by pressing the "Back" button, I see in the logs that onDestroy is called for activity, and onCleared is called for ViewModel.

But if I even run the application again after an hour, then the log immediately (without pressing a button) is displayed:

UserResult onChanged

UserResult NOT NULL

UserResult false null

But if after closing the application I do the cleaning of all running applications through the operating system, then nothing is displayed in the log.

Why were the ViewModel and LiveData not deleted even an hour after the application was closed? I guess I'm doing something wrong, please help me understand what my mistake is. Thank.

ViewModel

class UserViewModel extends ViewModel {

    private MutableLiveData<UserResult> userResult;
    private UserRepository userRepository;

    LiveData<UserResult> getUserResult() {
        return userResult;
    }

    UserViewModel(UserRepository userRepository) {
        this.userRepository = userRepository;
        userResult = userRepository.getUser(null);
    }

    void getUser(String username) {
        userResult = userRepository.getUser(username);
    }

    @Override
    protected void onCleared() {
        Log.d(TAG, "onCleared");
        super.onCleared();
    }
}

Repository

public class UserRepository {
    ...

    private WebServiceApi webServiceApi;

    private MutableLiveData<UserResult> data = new MutableLiveData<>();

    public MutableLiveData<UserResult> getUser(String username) {
        if (username != null) {
            webServiceApi.getUser(username).enqueue(new Callback<User>() {
                @Override
                public void onResponse(Call<User> call, Response<User> response) {
                    User user = response.body();
                    if (user == null) {
                        // first param = user, second param = userExistsFlag(true when user not null, false when user is null)
                        data.setValue(new UserResult(null, false));
                    } else {
                        data.setValue(new UserResult(user, true));
                    }
                }

                @Override
                public void onFailure(Call<User> call, Throwable t) {
                    Log.d("UserRepository", "onFailure " + t.getMessage());
                }
            });
        }

        return data;
    }
}

Activity

public class UserActivity extends AppCompatActivity {
    ...
    private UserViewModel userViewModel;


    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_user);

        ...

        userViewModel.getUserResult().observe(this, new Observer<UserResult>() {
            @Override
            public void onChanged(@Nullable UserResult userResult) {
                Log.d(TAG, "UserResult onChanged");

                if (userResult == null) {
                    return;
                } else {
                    Log.d(TAG, "UserResult NOT NULL");
                    Log.d(TAG, "UserResult " + userResult.getUserExistsFlag() + " " + userResult.getUser());
                }
            }
        });
    }

    @Override
    protected void onDestroy() {
        Log.d(TAG, "onDestroy");
        super.onDestroy();
    }

}

Solution

  • There isn't any mistake. This is an expected behavior. Android OS normally does not kill application processes when the user dismisses the application. There are few circumstances that OS kills the processes, but user closing the app is not one of them.

    If the application is alive, this means that all singleton classes are not going to be garbage collected. Your ViewModels will be discarded, but UserRepository and all its member variables won't, if UserRepository is using singleton pattern in some way. This is probably why your MutableLiveData<UserResult> data returns a value immediately.

    If you do not like this behavior, you probably shouldn't keep below line in UserRepository.

        private MutableLiveData<UserResult> data = new MutableLiveData<>();