CountDownTimer:在Activity,ViewModel或单独的类中?

时间:2019-06-24 09:07:58

标签: android android-lifecycle countdowntimer android-viewmodel

我想创建一个CountdownTimer,它将触发将更新UI的事件(触发弹出窗口,开始动画等)。

我想知道如何做到这一点,这是我的假设以及原因:

  1. 一个单独的组件EventCountdownTimer。这样我可以受益于LifecycleObserver的使用,但是我想知道如何将信息传达回活动(我尝试扩展CountdownTimer并在活动中使用它,但是我遇到了错误,无法获取进行编译)
  2. Activity本身中,它是最简单的,但由于它不是UI组件,因此我不确定它是否属于该组件,因此我无法从LifecycleObserver
  3. 中受益。
  4. ViewModel中。我认为与活动有关,CountdownTimer应该是逻辑数据,应该放在这里,但这也意味着要监视活动的生命周期,并在{{1}中保留任何与Activity相关的字段}是不好的做法。

根据您的最佳选择是什么?为什么呢?

3 个答案:

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