首页 > 解决方案 > 一段时间后如何使 ViewModel/LiveData 失效?

问题描述

根据最新文档的建议,我使用 ViewModel/LiveData 来显示一些数据:

public class EventDatesViewModel extends AndroidViewModel {

    private final MutableLiveData<String> timeToEvent = new MutableLiveData<>();

    ...

    public LiveData<String> getTimeToEvent() {
        if (timeToEvent == null)
            new Thread(this::calculateTimeToEvent).start();
        return timeToEvent;
    }

    private void calculateTimeToEvent() {

        ...

        timeToEvent.postValue(t);
    }
}

我在我的片段中使用它:

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View root = inflater.inflate(R.layout.fragment_garbage, container, false);

        EventDatesViewModel model = new ViewModelProvider(requireActivity(), new ViewModelProvider.AndroidViewModelFactory(requireActivity().getApplication())).get(EventDatesViewModel.class);
        model.getTimeToEvent().observe(this, timeToEvent -> {
            ((TextView)root.findViewById(R.id.textTimeToEvent)).setText(timeToEvent);
        });
        return root;
    }

现在的问题是timeToEvent类似于“2 天 4 小时”。因此,如果我让应用程序保持打开状态,在某些时候它会过时并且需要重新计算。如果应用程序未打开或在后台,我不想运行相当昂贵的计算。

我怎样才能实现这种定期重新计算?


什么没用

我添加了一个postDelayed()用于安排重新计算的处理程序。

    private final Handler handler = new Handler();
    private final Runnable runnable = new Runnable() {
        @Override
        public void run() {
            new Thread(() -> calculateTimeToEvent()).start();
            handler.postDelayed(this, 10000);
        }
    };
 public LiveData<String> getTimeToEvent() {
        if (timeToEvent == null) {
            new Thread(this::calculateTimeToEvent).start();
            handler.postDelayed(runnable, 10000);
        }
        return timeToEvent;
    }
    @Override
    protected void onCleared() {
        super.onCleared();
        handler.removeCallbacks(runnable);
    }

不幸的是,即使应用程序在后台或设备处于睡眠状态,这也会运行计算。我将calculateTimeToEvent()带有时间戳的运行记录到一个文件中,我可以看到它们每 10 秒发生一次,没有中断。

标签: androidmvvmandroid-livedataandroid-viewmodel

解决方案


由于您使用的是 Java,您可以使用 HandlerpostDelayed在 X 时间后触发可运行对象,然后在触发后再次安排它

这是 kotlin,但可以很容易地转回 Java

在您的视图模型中

private val _handler = Handler()

private val _runnable = object : Runnable {
    override fun run() {
        calculateTimeToEvent()
        _handler.postDelayed(this, 3600000)
    }

}

然后在某个时候在您的视图模型中调用它以开始重复操作

_handler.postDelayed(_runnable, 3600000)

然后在您的视图模型中,onCleared您可以删除回调以停止它

_handler.removeCallbacks(_runnable)

还有使用 RxJava 和使用的选项interval


推荐阅读