【发布时间】:2021-07-21 15:10:20
【问题描述】:
根据最新文档的建议,我正在使用 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 秒发生一次,没有中断。
【问题讨论】:
-
您是否在问如何安排每个
2 days 4 hours的重复操作? -
@tyczj 我在问如何安排每隔一小时左右重复一次操作,使其有权访问 ViewModel 以发布新值并且仅在以下情况下运行当前实际使用的是 ViewModel。
-
1.) 为什么要明确使用`new ViewModelProvider.AndroidViewModelFactory(requireActivity().getApplication()))`? Fragment 已经有一个具有更好行为的默认视图模型提供程序工厂 2.) 为什么使用
this作为 LifecycleOwner 而不是getViewLifecycleOwner()? -
@EpicPandaForce 1) 在我的 ViewModel 中,我需要一个
Context来显示 toast,所以它是一个AndroidViewModel,这是我能找到的最短的可以实例化AndroidViewModel的代码。 2) 我从here 复制了该代码,但似乎我混淆了这两个示例。 -
@EpicPandaForce 确实,在将 appcompat 更新到 1.3.1(从 1.2.0)之后,默认工厂工作并且它以某种方式触发了我应该使用
getViewLifecycleOwner()的 lintthis,就像你说的那样。谢谢。
标签: android mvvm android-livedata android-viewmodel