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();
}
}
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<>();