1
00:00:04,980 --> 00:00:07,500
G'day everyone, welcome back.

2
00:00:07,500 --> 00:00:11,140
In the last video we got our cursor adapter working.

3
00:00:11,140 --> 00:00:14,740
Well we think it's working. We know it hasn't broken anything

4
00:00:14,740 --> 00:00:17,720
and that it works fine when there is no data,

5
00:00:17,720 --> 00:00:24,460
but we can't test it further until we've created the view model class that's going to provide it with data.

6
00:00:24,460 --> 00:00:26,520
So let's get started.

7
00:00:26,520 --> 00:00:36,580
Right click on the project and choose
New Kotlin File/Class.

8
00:00:36,580 --> 00:00:45,540
I'll call it TaskTimerViewModel

9
00:00:45,540 --> 00:00:50,040
and select class from the drop-down.

10
00:00:50,040 --> 00:00:53,960
We saw how view models worked in the previous section.

11
00:00:53,960 --> 00:00:56,840
This one's going to be a slight variation.

12
00:00:56,840 --> 00:01:02,980
Instead of extending the ViewModel class
we'll extend an Android view model.

13
00:01:02,980 --> 00:01:08,960
Both classes work the same way.
AndroidViewModel is a subclass of ViewModel,

14
00:01:08,960 --> 00:01:11,760
but it also has an application property.

15
00:01:11,760 --> 00:01:15,660
That's going to be useful if we want to access the database,

16
00:01:15,660 --> 00:01:20,420
because we'll need an application to get a ContentResolver.

17
00:01:20,420 --> 00:01:31,440
So let's complete our TaskTimerViewModel declaration.

18
00:01:31,440 --> 00:01:39,640
Additionally, of course, let's put a tag
in to help with our logging.

19
00:01:39,640 --> 00:01:45,300
It's worth control clicking on the AndroidViewModel to check out the source code.

20
00:01:45,300 --> 00:01:49,360
That's command click on a Mac.

21
00:01:49,360 --> 00:01:52,140
Once again, this is Java code.

22
00:01:52,140 --> 00:01:57,460
So it's slightly more verbose than Kotlin
but it's easy enough to understand.

23
00:01:57,460 --> 00:02:01,980
AndroidViewModel is a subclass of ViewModel.

24
00:02:01,980 --> 00:02:07,600
The Java keyword, extends, is used to specify the superclass.

25
00:02:07,600 --> 00:02:10,880
As we said, it has an application property.

26
00:02:10,880 --> 00:02:17,080
The application property is set in the constructor,
which is a separate method in Java.

27
00:02:17,080 --> 00:02:23,660
You can write constructors that way in Kotlin, but it's more convenient to just use the primary constructor,

28
00:02:23,660 --> 00:02:27,300
and list the properties when defining the class.

29
00:02:27,300 --> 00:02:34,360
Being Java, it also has a getter for the
application, the getApplication function.

30
00:02:34,360 --> 00:02:37,260
This complicates our Kotlin code slightly

31
00:02:37,260 --> 00:02:42,820
because it allows the application argument to also be
a subclass of application.

32
00:02:42,820 --> 00:02:46,660
That's what the T extends Application means.

33
00:02:46,660 --> 00:02:52,840
It can return any type as long as that type is an Application,
or a subclass of it.

34
00:02:52,840 --> 00:02:57,100
You'll see the slight complication that this causes us, shortly.

35
00:02:57,100 --> 00:03:00,900
Ok, back to our ViewModel.

36
00:03:00,900 --> 00:03:06,120
We want it to make a cursor available via a LiveData object.

37
00:03:06,120 --> 00:03:11,880
We've seen that before. When the cursor changes,
observers will be notified of that change.

38
00:03:11,880 --> 00:03:16,460
In this case, the observer will be MainActivityFragment.

39
00:03:16,460 --> 00:03:22,660
When it gets notified of a change,
it'll swap the cursor in the RecyclerviewAdapter.

40
00:03:22,660 --> 00:03:34,600
We'll make our database cursor a private variable of type MutableLiveData.

41
00:03:34,600 --> 00:03:40,700
We'll define our cursor as a LiveData cursor

42
00:03:40,700 --> 00:03:45,340
and we'll return the database cursor in the get method.

43
00:03:45,340 --> 00:03:53,100
Our ViewModel will load the data from the database then update the database cursor LiveData object.

44
00:03:53,100 --> 00:03:56,000
We'll add that code in a separate function.

45
00:03:56,000 --> 00:04:00,760
We'll define our load tasks method.

46
00:04:00,760 --> 00:04:16,320
Our projection array will define the data table's columns.

47
00:04:16,320 --> 00:04:22,340
We'll put a comment in to remind us of
what we're doing,

48
00:04:22,340 --> 00:04:30,120
and we'll define our sort order.

49
00:04:30,120 --> 00:04:48,000
Then we'll define our cursor using to projection array and the sort order.

50
00:04:48,000 --> 00:04:51,880
Then we'll set the database cursor value.

51
00:04:51,880 --> 00:04:56,140
That's the standard code for fetching data from the ContentProvider.

52
00:04:56,140 --> 00:05:03,100
What might look a bit strange is the way we have to get the ContentResolver on line 25.

53
00:05:03,100 --> 00:05:09,220
As we're using Kotlin you may expect that we could refer to the application property directly,

54
00:05:09,220 --> 00:05:12,360
rather than calling the Java getter method.

55
00:05:12,360 --> 00:05:15,500
That's the slight complication I mentioned before.

56
00:05:15,500 --> 00:05:20,960
Because we have to specify the exact type of application inside the diamond operator,

57
00:05:20,960 --> 00:05:23,400
we must use the getter.

58
00:05:23,400 --> 00:05:29,060
It's a minor inconvenience, but does make the AndroidViewModel class more flexible,

59
00:05:29,060 --> 00:05:31,440
and it does it in a type-safe way.

60
00:05:31,440 --> 00:05:36,080
If you want to store the application parameter that was passed via the constructor,

61
00:05:36,080 --> 00:05:38,920
then you could create a property to store it.

62
00:05:38,920 --> 00:05:43,100
That would work, but I wanted to show you this strange syntax.

63
00:05:43,100 --> 00:05:45,640
I've also jumped the gun a bit here.

64
00:05:45,640 --> 00:05:52,620
On line 30, I've called the postValue
function to set up our database cursor's value.

65
00:05:52,620 --> 00:05:56,960
This is instead of assigning it
directly to its value property.

66
00:05:56,960 --> 00:05:59,880
You may remember, back in the previous section,

67
00:05:59,880 --> 00:06:04,100
that postValue was used when you're updating the value on a different thread

68
00:06:04,100 --> 00:06:08,040
to the one that the MutableLiveData object was created on.

69
00:06:08,040 --> 00:06:10,960
I won't say any more about that just yet

70
00:06:10,960 --> 00:06:15,100
because I'll be giving away the answer to a mini-challenge if I do.

71
00:06:15,100 --> 00:06:19,860
Ignore the warning about closing the cursor, if you get one on line 30.

72
00:06:19,860 --> 00:06:24,720
The warning's correct, it is our responsibility to close the
cursor.

73
00:06:24,720 --> 00:06:32,280
We can't do that now though. If we do, it will be invalid when the adapter tries to get the data from it.

74
00:06:32,280 --> 00:06:36,940
I mentioned that briefly when we wrote
the swap cursor function in our adapter.

75
00:06:36,940 --> 00:06:39,280
This is what I was referring to.

76
00:06:39,280 --> 00:06:43,480
The adapter doesn't own the cursor, so it shouldn't close it.

77
00:06:43,480 --> 00:06:47,860
We'll see how to deal with this when we've finished writing all the code.

78
00:06:47,860 --> 00:06:50,560
All right, we're just about done.

79
00:06:50,560 --> 00:06:55,000
All that remains is to call that loadTasks function.

80
00:06:55,000 --> 00:07:01,320
We can do that in an init block, which will be executed when the ViewModel instance gets created.

81
00:07:01,320 --> 00:07:15,220
I like to put init code at the start of the class, after the property and the variable declarations.

82
00:07:15,220 --> 00:07:19,692
We'll make sure that we log the start

83
00:07:19,700 --> 00:07:24,460
and then call our load tasks function.

84
00:07:24,460 --> 00:07:29,780
In the next video we'll subscribe to the
ViewModel and see it working.

85
00:07:29,780 --> 00:07:32,700
See you in the next one

