我想创建一个CountdownTimer
,它将触发将更新UI的事件(触发弹出窗口,开始动画等)。
我想知道如何做到这一点,这是我的假设以及原因:
EventCountdownTimer
。这样我可以受益于LifecycleObserver
的使用,但是我想知道如何将信息传达回活动(我尝试扩展CountdownTimer
并在活动中使用它,但是我遇到了错误,无法获取进行编译)Activity
本身中,它是最简单的,但由于它不是UI组件,因此我不确定它是否属于该组件,因此我无法从LifecycleObserver
ViewModel
中。我认为与活动有关,CountdownTimer
应该是逻辑数据,应该放在这里,但这也意味着要监视活动的生命周期,并在{{1}中保留任何与Activity
相关的字段}是不好的做法。根据您的最佳选择是什么?为什么呢?
答案 0 :(得分:1)
在MVVM模式中,您可以在ViewModel中观察到LiveData,UI可以观察到该数据,并在更改值后相应地更新UI。可观察的值如何变化,即您的业务逻辑,所有这些都应该在ViewModel或单独的组件中,ViewModel将使用它们来更新可观察的状态。
这将使您能够将UI与业务逻辑分开,这是您可以观察到的两者之间的沟通桥梁,而ViewModel不知道UI中发生了什么。用简单的话说,它只执行被告知要执行的操作并更新要观察的变量,然后在UI中发生的事情就是UI责任,与此相关,您已经清楚地将关注点分离了。
答案 1 :(得分:1)
单独的组件“ EventCountdownTimer”
我认为,这是您可能遇到的最佳实现。为了将信息传达回您的活动,您可以考虑使用如下所示的界面。
public interface TimerListener {
void onTimerResponse(String response);
}
修改您的EventCountdownTimer
,使其构造函数使用TimerListener
作为参数,并在您的活动中覆盖onTimerResponse
方法。现在,从EventCountdownTimer
开始,例如,当您尝试通过消息与活动进行通信时,您可以仅调用函数onTimerResponse(msgToDeliver)
。
因此,您的EventCountdownTimer
应该看起来像这样。
public class EventCountdownTimer {
public static Context context;
public static TimerListener listener;
public EventCountdownTimer(Context context, TimerListener listener) {
this.context = context;
this.listener = listener;
}
public startCountdown() {
// Start the count down here
// ... Other code
// When its time to post some update to your activity
listener.onTimerResponse(msgToDeliver);
}
}
然后根据您的活动,初始化EventCountdownTimer
,如下所示。
EventCountdownTimer timer = new EventCountdownTimer(this, new TimerListener() {
@Override
public void onTimerResponse(String message) {
// Do something with the message data
// Update your UI maybe
}
});
我认为您已经提供了充分的理由不使用您提到的其他选项。
答案 2 :(得分:0)
谷歌解决方案:see it on github
/**
* A ViewModel used for the {@link ChronoActivity3}.
*/
public class LiveDataTimerViewModel extends ViewModel {
private static final int ONE_SECOND = 1000;
private MutableLiveData<Long> mElapsedTime = new MutableLiveData<>();
private long mInitialTime;
private final Timer timer;
public LiveDataTimerViewModel() {
mInitialTime = SystemClock.elapsedRealtime();
timer = new Timer();
// Update the elapsed time every second.
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
final long newValue = (SystemClock.elapsedRealtime() - mInitialTime) / 1000;
// setValue() cannot be called from a background thread so post to main thread.
mElapsedTime.postValue(newValue);
}
}, ONE_SECOND, ONE_SECOND);
}
public LiveData<Long> getElapsedTime() {
return mElapsedTime;
}
@Override
protected void onCleared() {
super.onCleared();
timer.cancel();
}
}