Welcome back again. In the last video, we completed the changes to the various
database classes. They can now handle the new CurrentTimingView. We just need to
use it, in the TaskTimerViewModel class. I'll write the function
retrieveCurrentTiming, and add it near the end of the class, just before onCleared.
It's quite common, when querying a base view, to want all the columns.
You normally write the views to only contain the columns you'll use. The Content
Provider's query function will automatically return all columns when we
pass a null as the projection. If you created a projection, that's fine.
It won't do any harm - it's just unnecessary. Okay, if the cursor contains any rows,
then we've got a timing record to retrieve. It should contain zero or one
row, but we've written it to cope if more than one row's returned. The row we want
will be the first one, because we sorted the data onStartTime in reverse order.
The next bit of code is straightforward. We just get the data from the columns,
in the cursor, and create a new timing instance.
Android Studio is giving us a warning that we should close the cursor.
It didn't always do that, and it may stop doing it in the future, so don't rely on
these warnings. Get in the habit of closing resources like cursors, when you
finish processing them. We also need to return the timing object that we've created.
We're almost done, but there's something missing. The reason we created the
CurrentTimingView, is so that we'd have a task name to display. There's no point
going to all that trouble, if we don't display it, so let's do that. All we have
to do is update the taskTiming's Live Data object. MainActivity's observing it
and we'll update the display when it changes.
Alright, that's our retrieveTiming function finished.
It returns null if there's no record waiting to be timed,
otherwise, it returns a timing instance with the correct task ID and start time
When our ViewModel is created, it should use this function to retrieve any timing
that's still waiting to be timed. We can use this function to do that, in the init block.
I'll put it before the call to load tasks and then explain why.
Alright, why is it important to call retrieveTiming before loading the tasks?
If we load the tasks first, it's just possible that the user could long-tap one,
to start timing it. If they do that, we might not stop timing the task we're
trying to retrieve, because current task will still be null. By retrieving any
outstanding timing first, we can be sure that won't happen. That's also why we're
accessing the database on the main UI thread in retrieveTiming. We want the UI
to block there, to make sure everything's loaded before the user can interact with
the list of tasks. Remember, we're retrieving a single
record from the local database, and that shouldn't be a long-running task. We can
check how long it takes to execute, in logcat. Let's test the app to do that.
I'll make sure the logcat's visible. Make sure you use the green run triangle here -
don't use instant run. We want to make sure that the app is closed, and executed again.
If we had a timing record saved, the app will show that it's still being timed.
If we hadn't, it'll say No task being timed.
I'll relaunch the app in a moment and we'll run this test again. In the logcat,
we can see the retrieveTiming function starting. Don't forget that we can search
for the TaskTimerViewModel, to cut down the number of lines that we're
looking at. As you can see, the times for the start and the returning are the same,
meaning that the time taken is less than one millisecond, and a view had to be
created in that time as well. So the time executing the query is very, very short.
Your times may be different, however, especially if your emulator is running
slower than mine is. I'll start timing another task and then run the app again.
This time, once again, the total time is zero. That's definitely going to be
acceptable, but remember, this is running on a large computer, rather than on a
handheld device. In the next video, we'll see how the app behaves when the user's
battery runs out of charge. See you then.