1
00:00:04,400 --> 00:00:06,420
G'day everyone, welcome back.

2
00:00:06,420 --> 00:00:11,820
To finish moving our save code from AddEditFragment to TaskTimerViewModel

3
00:00:11,820 --> 00:00:15,080
we need to write the saveTask function in the ViewModel.

4
00:00:15,080 --> 00:00:25,980
I'll put it before the deleteTask function, because it seems more logical to have save before delete.

5
00:00:25,980 --> 00:00:35,160
So let's define our function, give ourselves
somewhere to store our information,

6
00:00:35,160 --> 00:00:44,280
and implement a little bit of business logic.
Remember, if the task name is empty we don't save.

7
00:00:44,280 --> 00:00:54,360
If it's not empty, let's collect up the values from the interface.

8
00:00:54,360 --> 00:00:59,180
Now, if the task id is zero it
means we have a new task.

9
00:00:59,180 --> 00:01:07,840
In which case, we need to add the new task.

10
00:01:07,840 --> 00:01:13,080
We'll make sure that we've got a valid URI, or at least, one that isn't null,

11
00:01:13,080 --> 00:01:17,220
and then we'll assign it an ID

12
00:01:17,220 --> 00:01:22,980
and of course, we log all of that just so we can track what's going on.

13
00:01:22,980 --> 00:01:30,460
If we do have an existing task, in other words, the ID was not equal to zero,

14
00:01:30,460 --> 00:01:39,240
then, once more, we just need to log

15
00:01:39,240 --> 00:01:44,100
and update our task.

16
00:01:44,100 --> 00:01:47,560
All of that's quite similar to the code we had in the fragment,

17
00:01:47,560 --> 00:01:52,600
simplified because we're not comparing the widgets to the original task.

18
00:01:52,600 --> 00:01:56,620
To decide whether we're saving a new task or updating an existing one,

19
00:01:56,620 --> 00:02:04,260
we check the ID. If the ID's zero, then the
task didn't come from the database and must be a new task.

20
00:02:04,260 --> 00:02:09,720
The logic to prevent a task being saved, if it's name is blank, also appears here.

21
00:02:09,720 --> 00:02:15,040
That's the business logic, and it belongs in the modelled layer not the UI layer.

22
00:02:15,040 --> 00:02:18,200
We need to test that the URI isn't null.

23
00:02:18,200 --> 00:02:25,520
That's what we do on line 73, because the ContentResolver's insert function can return null.

24
00:02:25,520 --> 00:02:30,160
Although we're using Kotlin, we can't escape from null checks completely,

25
00:02:30,160 --> 00:02:32,900
not as long as we're using Java classes.

26
00:02:32,900 --> 00:02:37,460
One thing that may not be obvious,
is why we're returning the task.

27
00:02:37,460 --> 00:02:41,340
We got it from the calling code, so why send it back?

28
00:02:41,340 --> 00:02:46,260
The reason is, that it may now have an ID
that it didn't have before.

29
00:02:46,260 --> 00:02:52,940
Let's have a quick look at the saveTask function in AddEditFragment.

30
00:02:52,940 --> 00:02:57,480
That's got a Task instance, which may be null for a new task.

31
00:02:57,480 --> 00:03:03,900
Now, at the moment, we've written the app so that the fragment is removed when we save the task.

32
00:03:03,900 --> 00:03:10,060
You may decide not to do that. The app may allow the user to keep making changes, and saving them.

33
00:03:10,060 --> 00:03:15,860
In that case, the fragment's Task instance
should reflect the data in the database.

34
00:03:15,860 --> 00:03:22,460
Otherwise, we could keep creating new
tasks when we save, instead of updating the one that now exists.

35
00:03:22,460 --> 00:03:31,180
That's why we assign the result of calling ViewModel's saveTask function,  back to the task.

36
00:03:31,180 --> 00:03:44,220
Okay, that's the function added.
Let's see if it works.

37
00:03:44,220 --> 00:03:53,240
We're upto task 8, so tap the plus icon in the toolbar and enter task 8 for the name,

38
00:03:53,240 --> 00:03:59,240
8th task for the description, and save.

39
00:03:59,240 --> 00:04:00,960
That's looking good.

40
00:04:00,960 --> 00:04:14,560
How about editing an existing task. I'll edit task 10,
and change 1st in its description, to first.

41
00:04:14,560 --> 00:04:19,940
Tap save again, and the entry's updated.

42
00:04:19,940 --> 00:04:21,459
Our change works.

43
00:04:21,459 --> 00:04:23,340
At the end of the last video,

44
00:04:23,340 --> 00:04:28,800
I asked you to think about whether the list in MainActivityFragment would be updated,

45
00:04:28,800 --> 00:04:33,020
if both fragments are using their own instance of the ViewModel.

46
00:04:33,020 --> 00:04:38,440
Clearly it does get updated, so here's a
mini challenge.

47
00:04:38,440 --> 00:04:49,300
How is MainActivityFragment receiving a new cursor, if it uses a different ViewModel instance to AddEditFragment?

48
00:04:49,300 --> 00:04:52,180
And here's the answer. The reason it works,

49
00:04:52,180 --> 00:04:58,900
is that both ViewModel instances are receiving notifications from a single ContentResolver.

50
00:04:58,900 --> 00:05:04,060
There is only one ContentResolver and it belongs to the application.

51
00:05:04,060 --> 00:05:08,520
It doesn't matter which instance of the ViewModel makes a change to the data,

52
00:05:08,520 --> 00:05:13,880
the ContentResolver will notify all its observers about that change.

53
00:05:13,880 --> 00:05:18,760
In the next video, we'll go through some slides to explain how all this is working.

54
00:05:18,760 --> 00:05:21,240
See you then.

