【问题标题】:ViewModel and LiveData are not deleted after the application is closed. Why?ViewModel 和 LiveData 在应用程序关闭后不会被删除。为什么?
【发布时间】:2019-11-15 08:36:33
【问题描述】:

我刚开始学习 android 开发,遇到了问题,很高兴得到任何帮助。

当我点击“用户存在?”按钮,向服务器发送请求,服务器返回用户或 null(在我的情况下,始终为 null,因为服务器上没有创建用户)。

点击观察者中的按钮后,日志中显示如下:

用户结果 onChanged

用户结果不为空

UserResult false null

也就是说,一切都很完美。

当我通过按“返回”按钮关闭应用程序时,我在日志中看到 onDestroy 被称为活动,而 onCleared 被称为 ViewModel。

但如果我在一小时后再次运行该应用程序,则会立即显示日志(无需按下按钮):

用户结果 onChanged

用户结果不为空

UserResult false null

但是如果关闭应用程序后我通过操作系统清理所有正在运行的应用程序,那么日志中不会显示任何内容。

为什么在应用程序关闭一小时后 ViewModel 和 LiveData 仍未删除?我想我做错了什么,请帮助我理解我的错误是什么。谢谢。

视图模型

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

存储库

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

活动

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

}

【问题讨论】:

  • 你为什么希望它们为空?
  • @Blackbelt 我不太明白你的意思

标签: android mvvm viewmodel android-livedata mutablelivedata


【解决方案1】:

没有任何错误。这是预期的行为。 Android 操作系统通常不会在用户关闭应用程序时终止应用程序进程。操作系统杀死进程的情况很少,但关闭应用程序的用户不是其中之一。

如果应用程序处于活动状态,这意味着所有单例类都不会被垃圾回收。您的 ViewModel 将被丢弃,但 UserRepository 及其所有成员变量不会,如果 UserRepository 以某种方式使用单例模式。这可能就是您的MutableLiveData&lt;UserResult&gt; data 立即返回值的原因。

如果您不喜欢这种行为,您可能不应该在UserRepository 中保持以下行。

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

【讨论】:

  • 感谢您的回复。当我重新启动应用程序时,会创建一个新的 Activity、一个新的 ViewModel 和一个新的存储库,在这种情况下,旧存储库中的数据(未被 GC 删除)如何进入新的 Activity?新 Activity 包含指向新 ViewModel 的链接,新 ViewModel 存储指向新 Repository 的链接。或不?我哪里错了?如果我问愚蠢的问题,我很抱歉,我是新手。
  • @aqellaa 当您重新启动应用程序时,会创建一个新的 Activity、一个新的 ViewModel,但可能不会创建一个新的存储库。我不能肯定地告诉你,因为你没有提供初始化 Repository 类的代码部分,这只是问题中提供的信息的有根据的猜测。
  • My Repository 是一个单例类,正如你所建议的。我是否正确理解如果这是一个单例,那么当我重新启动应用程序时,它很可能不是新创建的?
  • 是的。用户将获得用户关闭应用程序之前使用的相同 Repository 实例。
  • 感谢您提供如此详细的答案,您对我帮助很大。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-24
  • 2017-03-31
  • 1970-01-01
  • 2012-06-04
  • 1970-01-01
相关资源
最近更新 更多