I create simple Android application and I try to use MVP design pattern. I read some tutorials and after that I started writing code. Now I have simple activity with its functionality and my code looks like this.
View:
interface TimerView { fun updateTime(time: Long) fun disableStop() fun disableStart() fun disablePause() fun enableStop() fun enableStart() fun enablePause() } class MainActivity : AppCompatActivity(), TimerView { private var presenter = TimerPresenter(this) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) setSupportActionBar(toolbar) } override fun onResume() { super.onResume() presenter.restoreState(this) } override fun onPause() { super.onPause() presenter.saveState(this) presenter.stopTimer() } fun stopTimer(view: View) { presenter.stopTimer() presenter.resetTimer() } fun startTimer(view: View) { presenter.startTimer() } fun pauseTimer(view: View) { presenter.pauseTimer() } override fun updateTime(time: Long) { timeText.text = timeToString(time) } override fun disableStop() { stopFab.isEnabled = false } override fun disableStart() { startFab.isEnabled = false } override fun disablePause() { pauseFab.isEnabled = false } override fun enableStop() { stopFab.isEnabled = true } override fun enableStart() { startFab.isEnabled = true } override fun enablePause() { pauseFab.isEnabled = true } }
Presenter:
class TimerPresenter(private val view: TimerView) : TimerListener { private val timer = Timer(this) fun stopTimer() { timer.stop() } fun startTimer() { timer.start() } fun pauseTimer() { timer.pause() } fun resetTimer() { timer.reset() } fun saveState(context: Context) { timer.saveState(context) } fun restoreState(context: Context) { timer.restoreState(context) } private fun setStopView() { view.disableStop() view.disablePause() view.enableStart() } private fun setStartView() { view.disableStart() view.enableStop() view.enablePause() } private fun setPauseView() { view.disablePause() view.enableStop() view.enableStart() } private fun setViewState(state: TimerData.State) { when (state) { TimerData.State.Stop -> setStopView() TimerData.State.Run -> setStartView() TimerData.State.Pause -> setPauseView() } } private fun updateTimer(timeRemaining: Long) { view.updateTime(timeRemaining) } override fun onTimerFinish() { timer.reset() } override fun onTimerTick(timeRemaining: Long) { updateTimer(timeRemaining) } override fun onTimerStateChange(newState: TimerData.State) { setViewState(newState) } override fun onTimerReset(timeRemaining: Long) { updateTimer(timeRemaining) } override fun onTimerStateRestored(timeRemaining: Long, state: TimerData.State) { updateTimer(timeRemaining) setViewState(state) if (state == TimerData.State.Run) { timer.start() } } }
Model:
interface TimerListener { fun onTimerFinish() fun onTimerTick(timeRemaining: Long) fun onTimerStateChange(state: TimerData.State) fun onTimerReset(timeRemaining: Long) fun onTimerStateRestored(timeRemaining: Long, state: TimerData.State) } data class TimerData(var state: State = State.Stop, var timerLength: Long = 0L, var timeRemaining: Long = 0L) { enum class State { Stop, Run, Pause } fun loadData(context: Context) { state = PrefUtils.getState(context) timerLength = PrefUtils.getTimerLength(context) timeRemaining = if (state != State.Stop) { PrefUtils.getTimeRemaining(context) } else { timerLength } } fun saveData(context: Context) { PrefUtils.setState(context, state) PrefUtils.setTimeRemaining(context, timerLength) PrefUtils.setTimeToStop(context, timeRemaining) } fun reset() { timeRemaining = timerLength } } class Timer(private val listener: TimerListener) { private var data = TimerData() private var timer: CountDownTimer? = null fun start() { timer = object : CountDownTimer(data.timeRemaining * 1000L, 1000L) { override fun onFinish() { stop() listener.onTimerFinish() } override fun onTick(millisUntilFinished: Long) { --data.timeRemaining listener.onTimerTick(data.timeRemaining) } }.start() data.state = TimerData.State.Run listener.onTimerStateChange(data.state) } fun stop() { timer?.cancel() data.state = TimerData.State.Stop listener.onTimerStateChange(data.state) } fun pause() { timer?.cancel() data.state = TimerData.State.Pause listener.onTimerStateChange(data.state) } fun reset() { data.reset() listener.onTimerReset(data.timeRemaining) } fun saveState(context: Context) { data.saveData(context) } fun restoreState(context: Context) { data.loadData(context) listener.onTimerStateRestored(data.timeRemaining, data.state) } }
Did I separate tasks correctly between classes or maybe there is something wrong with my code?