1
00:00:04,580 --> 00:00:06,660
G'day everyone, welcome back.

2
00:00:06,660 --> 00:00:14,360
In this video, we're going to remove the dependency that our AddEditFragment has on the content resolver.

3
00:00:14,360 --> 00:00:20,500
Instead of saving the task details, it will just pass them on to TaskTimerViewModel,

4
00:00:20,500 --> 00:00:23,620
and the ViewModel will take care of saving them.

5
00:00:23,620 --> 00:00:30,140
We've got a small optimisation in AddEditFragment's code to save the task details.

6
00:00:30,140 --> 00:00:34,860
It's described in the comment at the start of the saveTask function.

7
00:00:34,860 --> 00:00:38,760
We'll only save the details if something has changed.

8
00:00:38,760 --> 00:00:43,620
That's not business logic, and I'm going to leave that test in the fragment.

9
00:00:43,620 --> 00:00:49,760
If you're not sure whether something counts as business logic, and therefore whether it belongs in the model,

10
00:00:49,760 --> 00:00:55,220
ask the question,
Would the program still give the same results without it?

11
00:00:55,220 --> 00:01:02,000
Here, the program would still do the same thing if we saved the data, regardless of whether it had changed or not.

12
00:01:02,000 --> 00:01:06,760
It would be less efficient, obviously, but the results would be the same.

13
00:01:06,760 --> 00:01:13,580
We have got a bit of business logic in here. The code checks to see if the task name isn't empty.

14
00:01:13,580 --> 00:01:20,260
That's not something the UI should be concerned with,
so that test will be moved to the ViewModel.

15
00:01:20,260 --> 00:01:24,120
I'm also going to reverse the decision that we made earlier.

16
00:01:24,120 --> 00:01:30,780
When we looked at Kotlin data classes,
we decided not to make Task a data class.

17
00:01:30,780 --> 00:01:35,680
That decision was made before Google deprecated the Loader classes.

18
00:01:35,680 --> 00:01:39,860
While changing the code from using a Loader to using a ViewModel,

19
00:01:39,860 --> 00:01:44,320
it became clear that a data class would provide some benefit.

20
00:01:44,320 --> 00:01:52,860
The important benefit we'll get, is the ability to compare
two Task objects, so I'm going to make my Task a data class.

21
00:01:52,860 --> 00:02:00,940
You'll see why in a moment.

22
00:02:00,940 --> 00:02:07,140
While we're here, we've got a warning that id won't be serialized into a parcel.

23
00:02:07,140 --> 00:02:10,660
That was fine, but now we're going to need it to be.

24
00:02:10,660 --> 00:02:17,800
The fix is to move it into the primary constructor,

25
00:02:17,800 --> 00:02:26,960
and this time I'll accept Android Studio's suggestion, and remove the empty class body.

26
00:02:26,960 --> 00:02:32,980
Just to be clear, I've made those changes because the app was originally written to use a Loader.

27
00:02:32,980 --> 00:02:37,860
Google's decision to deprecate the Loader classes came as a bit of a surprise,

28
00:02:37,860 --> 00:02:41,660
and we've modified the app to use a ViewModel instead.

29
00:02:41,660 --> 00:02:46,180
By using a data class, we can make our next bit of code simpler.

30
00:02:46,180 --> 00:02:52,320
Okay, time to make some changes to AddEditFragment.

31
00:02:52,320 --> 00:02:59,420
At the moment the saveTask function is using values from the EditText widgets in the layout.

32
00:02:59,420 --> 00:03:05,880
Our ViewModel has no knowledge of those widgets, and we're going to pass it a Task object instead.

33
00:03:05,880 --> 00:03:13,900
Later in the course, you'll see another place where we need to create a new task from the contents of the EditText widgets.

34
00:03:13,900 --> 00:03:18,140
To save time later, I'm going to create a new function to do that.

35
00:03:18,140 --> 00:03:25,400
I'll call it task from UI, and add it before the saveTask function.

36
00:03:25,400 --> 00:03:30,940
We'll define the function, we'll get value for sortOrder.

37
00:03:30,940 --> 00:03:39,120
If it's not empty, then we're going to return the values that already exist by parsing it from the string,

38
00:03:39,120 --> 00:03:53,220
Otherwise, we'll return a zero, we'll make our new task,
assign it an ID, and then return it.

39
00:03:53,220 --> 00:03:58,560
As we said, if there's a value in the sortOrder widget,
we'll convert it to an integer.

40
00:03:58,560 --> 00:04:00,800
Otherwise, we'll set it to zero.

41
00:04:00,800 --> 00:04:07,360
When we create the new task, we'll use the contents of the EditText widgets for its properties.

42
00:04:07,360 --> 00:04:12,900
If we were editing an existing task, we also store the existing task ID.

43
00:04:12,900 --> 00:04:19,959
I used the Elvis operator on line 73, to assign the value 0 if the fragment's task is null.

44
00:04:19,959 --> 00:04:22,920
In other words, if we're adding a new task.

45
00:04:22,920 --> 00:04:25,840
That removes a lot of code from saveTask.

46
00:04:25,840 --> 00:04:37,860
In fact, it's now easier to delete the entire contents of saveTask and start again, rather than trying to change it.

47
00:04:37,860 --> 00:04:41,080
Let's define the function.

48
00:04:41,080 --> 00:04:50,440
We'll add a comment so that we remember what this is for.

49
00:04:50,440 --> 00:04:58,160
We'll create our new Task object, and we'll get the values from our EditText widgets.

50
00:04:58,160 --> 00:05:03,340
Then we'll check to see if it's the same task that we were given, when the fragment was created.

51
00:05:03,340 --> 00:05:05,700
The tasks we're editing, in other words.

52
00:05:05,700 --> 00:05:09,860
If they're not the same, then at least one
thing has changed,

53
00:05:09,860 --> 00:05:13,000
and we'll call the saveTask function in the ViewModel.

54
00:05:13,000 --> 00:05:17,860
We haven't written that yet but we'll do that next.

55
00:05:17,860 --> 00:05:20,920
This is why I made the task a data class.

56
00:05:20,920 --> 00:05:27,880
We can compare two task instances, because a data class provides an equals function for us.

57
00:05:27,880 --> 00:05:34,540
We've got a suggestion the dot equals can be replaced with the binary operator.

58
00:05:34,540 --> 00:05:40,020
Use a light bulb to accept the suggestion.

59
00:05:40,020 --> 00:05:43,580
If you're used to Java, that may horrify you.

60
00:05:43,580 --> 00:05:51,540
Don't worry. Using the equals equals and the not equals operators with data classes works fine, in Kotlin.

61
00:05:51,540 --> 00:06:05,800
Our AddEditFragment doesn't have a ViewModel,
so we'd better give it one.

62
00:06:05,800 --> 00:06:11,340
I've declared that slightly differently to the way it's declared in MainActivityFragment.

63
00:06:11,340 --> 00:06:16,900
The difference is subtle but important, and it's a good point to explain it.

64
00:06:16,900 --> 00:06:24,620
To see the difference, I'll copy the declaration from MainActivityFragment, and paste it below this one.

65
00:06:24,620 --> 00:06:29,240
Okay, the difference is in what we're passing as the scope.

66
00:06:29,240 --> 00:06:33,460
In MainActivityFragment we pass the fragment's activity.

67
00:06:33,460 --> 00:06:36,440
Here, we're passing the fragment.

68
00:06:36,440 --> 00:06:40,260
In this app, our fragments don't communicate with each other.

69
00:06:40,260 --> 00:06:46,560
They're totally independent, and aren't observing the same LiveData objects in the ViewModel.

70
00:06:46,560 --> 00:06:50,280
Sometimes, you will want fragments to share some data.

71
00:06:50,280 --> 00:06:54,300
In that case, you can pass the activity as the scope.

72
00:06:54,300 --> 00:06:59,020
Both fragments will then be observing data in the same ViewModel instance,

73
00:06:59,020 --> 00:07:05,520
and that ViewModel will exist as long as the activity does, surviving configuration changes too.

74
00:07:05,520 --> 00:07:09,700
You can find more information about this, here.

75
00:07:09,700 --> 00:07:14,940
The code samples have been converted to Kotlin. They're no longer just in Java.

76
00:07:14,940 --> 00:07:19,520
Unfortunately, there's an error in the Kotlin code at the moment.

77
00:07:19,520 --> 00:07:23,240
On the Java tab, for the example,

78
00:07:23,240 --> 00:07:33,560
both the master fragment and the detail fragment are passing the activity,

79
00:07:33,560 --> 00:07:35,560
and the document refers to that.

80
00:07:35,560 --> 00:07:45,220
At the moment, in the Kotlin code, and I'll click the Kotlin tab, it is this that is being passed in to both fragments.

81
00:07:45,220 --> 00:07:51,620
When you're reading through this, the text only makes sense if activity is passed as the scope there.

82
00:07:51,620 --> 00:07:56,580
So hopefully, by the time you watch this, they'll have corrected the documentation.

83
00:07:56,580 --> 00:08:04,340
I'll go through all this with some slides soon. It's worth reading through this document, after watching that video.

84
00:08:04,340 --> 00:08:08,980
Now, I've said that our fragments don't
communicate with each other, and that's true.

85
00:08:08,980 --> 00:08:14,740
However, AddEditFragment's going to
update the database via the ViewModel

86
00:08:14,740 --> 00:08:20,000
When that happens, the ViewModel will
provide changes to the MainActivityFragment.

87
00:08:20,000 --> 00:08:25,220
Will that work, if the two fragments aren't sharing the same ViewModel instance?

88
00:08:25,220 --> 00:08:30,980
If you get the right answer to that question, then you obviously understand how all this fits together.

89
00:08:30,980 --> 00:08:37,419
Don't worry if you got the wrong answer. We've got some diagrams coming up that will explain how it all works.

90
00:08:37,419 --> 00:08:41,740
I think it's worth demonstrating, rather than just telling you the answer.

91
00:08:41,740 --> 00:08:47,560
I'll delete the declaration that I've
just pasted in,

92
00:08:47,560 --> 00:08:53,360
and we'll leave AddEditFragment observing its own ViewModel, just to see what happens.

93
00:08:53,360 --> 00:08:59,980
Okay. I'll stop the video there.
In the next video, we'll add the saveTask function to the view model,

94
00:08:59,980 --> 00:09:04,600
and test the changes,
and we'll fix the error that we've got in the saveTask function.

95
00:09:04,600 --> 00:09:07,380
See you in the next one.

