Welcome back. We've got the Timings table in the database now, and we're ready to
save the Timings data. When the user long-taps a task, we'll create a new Timing
instance. When they long-tap a second time, we'll use the Timing instance to
provide the data to save. The app isn't going to run a timer.
Instead, we'll save the details when a task starts to be timed, then update the
duration when it's stopped. We need a Timing class to store the data.
Let's create that first. It'll be a basic Kotlin class and we'll define the fields
in the constructor. We need fields to store the task ID, the start time and the
timings database ID.
If you're prompted for the date import, we want Java dot util dot date.
I've made a setter for the duration field private, on line 16. That prevents
the code from changing the duration directly. The only way to set the
duration is by calling our setDuration function. Using Kotlin's normal property
access isn't suitable, in this case, because the calling code won't be
providing a new value for the duration. Instead, the duration is calculated by
subtracting the start time from the current time. When we create a new timing
record, the task that's being timed and the start time will never change.
The timing ID will change - it starts off at 0 and gets given a value once the record's
saved in the database. By using val for the task ID and start time fields,
we make sure they can't be changed, once the timing instance is created. I've used
default values for start time and the ID. Unless we need to provide values for
them, we only have to provide the task ID when creating a new timing. The other
fields will be initialized to the current time, and 0. The time that we get
from the date class is in milliseconds. That's a bit extreme for our purposes.
We're going to be working in seconds, not milliseconds. That's why the values are
divided by a thousand, in the constructor and on line 20. Alright that's the timing
class created. Next, we need to add some code to our TaskTimerViewModel class
I'll start with a variable to store the timing.
We'll set that to a new task instance, when the user starts timing a task.
I'll call the function timeTask and put it after the deleteTask function.
I've commented out all the calls to saveTiming because we haven't written it yet.
Before I do, I'll go through the logic of this timeTask function. I've used a
local variable - timingRecord - to allow smart casts. We know that nothing's
altering our timing instance on another thread,
so basically, timingRecord and currentTiming will be referring to exactly the
same object. We start by checking to see if we have a currentTiming instance.
If currentTiming is null, there's no task being timed, and we just
create a new timing instance and save it. That's easy. It's a bit more interesting
if you've already got a task being timed. If there is a task currently being timed,
we start by updating its' duration and saving it. Next, we have to decide whether
we got here because the new task was long-tapped, or if the user long-tapped
the same task to stop it. If the task ID is the same as the task we were timing,
then we stop timing and we don't have to create a new timing instance. We set
currentTiming to null, on line 114. On the other hand, if the task ID is
different, then the user long-tapped a different task. In that case, we create a
new timing instance to save it. Note that the new timing instances are saved as
soon as they're created. They'll be stored in the database, with a duration
of zero. The user can turn their phone off, at this point, if they have to.
When they turn it back on again, they can stop timing the task, and the database row
will be updated with the correct duration. I'll build up the full
functionality, as we write more code. That's how it's going to work, but we'll
start by getting the basic saving working. In the next video, we'll write
that saveTiming function. I'll see you there.