1
00:00:05,120 --> 00:00:07,340
So we're well on the way to getting this app finished.

2
00:00:07,410 --> 00:00:12,030
We just need some way now to pass the search results back to MainActivity.

3
00:00:12,050 --> 00:00:17,610
Now a good solution here would be to use something called shared preferences. Now shared preferences provides a way

4
00:00:17,610 --> 00:00:22,810
to store up data, so you can retrieve the data again next time the app starts up.

5
00:00:22,920 --> 00:00:27,540
They're not as powerful as a full database, but for many applications where you don't have to store

6
00:00:27,540 --> 00:00:33,490
a lot of data, they're ideal. And the other good thing is that they're also very easy to use, and they

7
00:00:33,500 --> 00:00:36,510
work in a similar way to the bundles that we've used before.

8
00:00:36,750 --> 00:00:41,910
So you store data in key value pairs, and retrieve the data items by specifying the key.

9
00:00:42,200 --> 00:00:47,520
So I'm going to add the code now to the onQueryTextSubmit function in search activity, just so you 

10
00:00:47,570 --> 00:00:48,960
can see what it does.

11
00:00:52,830 --> 00:00:57,520
So onQueryTextSubmit, we're going to add code after the logging,

12
00:00:57,700 --> 00:01:12,380
and we'll start with val sharedPref equals PreferenceManager.getDefaultSharedPreferences, then parentheses,

13
00:01:12,410 --> 00:01:16,700
and it's going to be applicationContext.

14
00:01:16,700 --> 00:01:24,730
Then we're going to do sharedPref dot edit, we're actually calling the edit function, so there's parentheses dot putString

15
00:01:25,220 --> 00:01:28,730
parentheses, and it's going to be flickr query

16
00:01:28,980 --> 00:01:33,730
comma space query closing parentheses dot

17
00:01:33,820 --> 00:01:41,020
apply. We're calling the apply function, and then we're going to do searchView question mark dot

18
00:01:41,220 --> 00:01:47,390
clearFocus, and then we're going to leave the call to finish and then return true.

19
00:01:47,420 --> 00:01:53,840
So what we're doing here is starting out on line 41. We're getting a shared preferences object by calling the Preference

20
00:01:53,840 --> 00:01:58,960
Manager's getDefaultSharedPreferences function, passing it a context.

21
00:01:58,970 --> 00:02:04,550
Now here we want to pass the application context rather than using this, because the date is going to

22
00:02:04,550 --> 00:02:08,490
be retrieved by a different activity to the one that saved it.

23
00:02:08,539 --> 00:02:12,900
Now SearchActivity will store the data and MainActivity will retrieve it.

24
00:02:12,920 --> 00:02:19,250
Now we have to call the edit function on the next line, line 42, to put the shared preferences into a writable

25
00:02:19,250 --> 00:02:25,820
state, and then we use the, we call the putString function to store the search query string.

26
00:02:25,820 --> 00:02:31,420
Now we store the string using the flickr query constant that we defined in base activity as the key. Now

27
00:02:31,430 --> 00:02:36,980
MainActivity and SearchActivity can both use the same constant, which ensures that they're both using

28
00:02:36,980 --> 00:02:43,090
the same key when saving and retrieving the data, and the data's then installed when we call the apply function.

29
00:02:43,120 --> 00:02:46,410
Now it's not obvious why we need to call clear focus in there,

30
00:02:46,590 --> 00:02:51,530
and you wouldn't normally find out what problem it solves, unless you tested the app on a device with

31
00:02:51,530 --> 00:02:53,300
an external keyboard.

32
00:02:53,300 --> 00:02:55,120
Now fortunately our emulators

33
00:02:55,130 --> 00:03:00,380
can use the PC's keyboard, so you can spot the strange behavior if we leave that out.

34
00:03:00,380 --> 00:03:06,200
Now the problem it fixes, is if you type a search query, then use the keyboard's enter key to submit it.

35
00:03:06,200 --> 00:03:09,000
Now when you do that the search icon in MainActivity

36
00:03:09,050 --> 00:03:12,990
also receives a click event, and just launches search activity again.

37
00:03:13,010 --> 00:03:15,410
And in fact you saw me do that in the previous video,

38
00:03:15,560 --> 00:03:20,510
when I pressed enter, entering a search query before I ended up actually correctly pressing the arrow

39
00:03:20,570 --> 00:03:22,050
down the bottom right hand corner.

40
00:03:22,430 --> 00:03:27,140
So I'm going to leave you to comment that line out and try it, so you can see why we need to remove focus from

41
00:03:27,140 --> 00:03:30,090
the toolbar before returning to MainActivity.

42
00:03:30,160 --> 00:03:36,560
And remember that you'll only see the different behavior when you press enter on an external keyboard. Alright so

43
00:03:36,590 --> 00:03:37,970
to get the data back,

44
00:03:38,030 --> 00:03:42,510
we just read the same key from the shared preference when main activity resumes.

45
00:03:42,590 --> 00:03:48,630
So let's go back and edit the MainActivity onResume function, and put some code in there. So I'm going to

46
00:03:48,640 --> 00:03:52,350
leave the call to super onResume. On the next line we'll do val 

47
00:03:52,820 --> 00:04:02,530
sharedPref is equal to, and its PreferenceManager.getDefaultSharedPreferences application context

48
00:04:02,530 --> 00:04:14,570
again. Then we're going to do val query result is equal to sharedPref.getString parentheses, and it's going to be

49
00:04:15,140 --> 00:04:21,410
flickr underscore query comma and two double quotes, closing parentheses.

50
00:04:21,540 --> 00:04:26,000
Next we're going to write a bit of code here. We're going to put if parentheses queryResult

51
00:04:26,000 --> 00:04:29,910
dot isNotEmpty,

52
00:04:30,100 --> 00:04:31,030
and we'll just add a blank

53
00:04:31,080 --> 00:04:33,830
code block for now. Then on the next line we're going to do some logging,

54
00:04:33,830 --> 00:04:40,970
so Log.d parentheses TAG comma double quotes dot onResume ends.

55
00:04:41,040 --> 00:04:44,990
So basically this is just the reverse of what we did to store the data.

56
00:04:45,230 --> 00:04:50,910
So we're creating a shared preferences object on line 120, using exactly the same code actually,

57
00:04:50,950 --> 00:04:56,310
then using the getString function to read the search string from the stored shared preferences on line

58
00:04:56,380 --> 00:04:59,060
21. Now there's no point downloading

59
00:04:59,100 --> 00:04:59,790
anything

60
00:04:59,960 --> 00:05:05,930
if no search criteria was specified, so we're checking to make sure the query result string isn't empty

61
00:05:06,230 --> 00:05:08,570
before attempting to download and parse the data.

62
00:05:08,580 --> 00:05:13,310
Or at least that's the code we're going to be using when we start filling that out from line 24. The getString

63
00:05:13,310 --> 00:05:16,730
function will attempt to retrieve the data stored with the key flickr query,

64
00:05:17,030 --> 00:05:22,930
but if it can't find the data with that key, it's going to return the second value we've passed it, an empty string

65
00:05:22,940 --> 00:05:26,260
in this case. So that's what this second argument's all about.

66
00:05:26,480 --> 00:05:32,790
Passing an empty string allows us to check to make sure we did get a search term from the user. OK.

67
00:05:32,910 --> 00:05:37,970
So if the user did specify something to search for, then we just repeat the code in onCreate to

68
00:05:37,970 --> 00:05:39,350
download the new data.

69
00:05:39,680 --> 00:05:41,430
And in fact we don't need to repeat it.

70
00:05:41,570 --> 00:05:44,230
We can just move that code into onResume.

71
00:05:44,240 --> 00:05:47,900
Remember that onResume's called after onCreate.

72
00:05:48,200 --> 00:05:53,600
So what I'm going to do is cut three lines from onCreate, and paste them into this empty if block in the

73
00:05:53,600 --> 00:05:58,770
onResume function. So back to onCreate. So the three lines

74
00:05:58,770 --> 00:05:59,700
that we want are these here,

75
00:05:59,720 --> 00:06:00,130
val

76
00:06:00,150 --> 00:06:04,790
url, the val getRawData and then the execute. So I'm going to copy those,

77
00:06:04,790 --> 00:06:11,350
or cut those rather. I'll just clear that up a little bit. Then go down to the resume, the

78
00:06:11,450 --> 00:06:13,360
onResume function.

79
00:06:13,360 --> 00:06:15,710
I'm going to paste that in here.

80
00:06:16,720 --> 00:06:18,890
So that's now called in the onResume function.

81
00:06:19,020 --> 00:06:24,070
And again, just to repeat, onResume's called after on Create.

82
00:06:24,120 --> 00:06:29,920
So therefore by putting it in onResume, we still guarantee that this code is going to be executed.

83
00:06:30,300 --> 00:06:37,170
Alright, so at this point all that remains to do, is to pass query result to the Create uri function, instead

84
00:06:37,170 --> 00:06:43,420
of the hardcoded string Android Oreo that we've currently got over here.

85
00:06:43,530 --> 00:06:47,640
So let's do that. Let's get rid of this, remove the hardcoded string there,

86
00:06:50,660 --> 00:06:53,670
and we're going to replace that instead with queryResult.

87
00:06:56,910 --> 00:06:58,500
Alright so that should work now,

88
00:06:58,500 --> 00:06:59,410
so let's test it.

89
00:07:04,980 --> 00:07:10,140
Now this time when I ran the app there's no data displayed, but that's because there wasn't any shared preference

90
00:07:10,140 --> 00:07:11,480
data to retrieve.

91
00:07:11,760 --> 00:07:16,440
So we have to do a search before we get any photo's returned. I'm going to go ahead and search for marshmallow

92
00:07:16,440 --> 00:07:17,330
again.

93
00:07:23,140 --> 00:07:27,620
And success as you can see there. We've got a load of photo's tagged now with marshmallow.

94
00:07:27,890 --> 00:07:31,540
Now we can narrow that down a little bit by searching for Android marshmallow.

95
00:07:31,820 --> 00:07:35,690
So let's try that, android comma marshmallow,

96
00:07:39,330 --> 00:07:41,990
and you can see we're getting some different results based on that as well,

97
00:07:45,770 --> 00:07:47,570
not particularly appropriate to Android marshmallow

98
00:07:47,610 --> 00:07:49,500
so let's just try another one to make sure.

99
00:07:49,670 --> 00:07:50,490
We'll try android 

100
00:07:50,530 --> 00:07:50,950
nougat,

101
00:07:54,530 --> 00:08:00,290
and we've got some more computer related results there, android nougat showing. So clearly that's working fine.

102
00:08:00,300 --> 00:08:00,590
Alright.

103
00:08:00,600 --> 00:08:02,080
So that's great,

104
00:08:02,220 --> 00:08:06,860
but what happens if a user decides that they don't want to search though, and clicks the X to cancel.

105
00:08:06,880 --> 00:08:08,560
Let's try that.

106
00:08:08,590 --> 00:08:14,780
So if they're here and they decide that they don't want to proceed with a search, click on X. Now that's not good.

107
00:08:15,000 --> 00:08:18,680
It's closed the search view but it doesn't return to MainActivity.

108
00:08:18,870 --> 00:08:25,020
But we saw, if you recall, an onClose function in the documentation, so we can implement that listener

109
00:08:25,380 --> 00:08:30,000
and call finish if the user closes the search view instead of submitting a search.

110
00:08:30,320 --> 00:08:35,190
So let's go ahead and create that, or add that rather, to the onCreateOptionsMenu function in Search

111
00:08:35,190 --> 00:08:38,900
Activity.

112
00:08:39,080 --> 00:08:43,409
We want to add it down here, before the closing onCreateOptionsMenu

113
00:08:43,530 --> 00:08:46,610
log entry, so add it there.

114
00:08:46,610 --> 00:08:48,350
Let's add a bit of space.

115
00:08:48,890 --> 00:08:58,710
So I'm going to do searchView question mark dot, we're going to set an onCloseListener, like so, and the code we want to execute in

116
00:08:58,740 --> 00:09:02,440
there is finish and then false.

117
00:09:02,810 --> 00:09:07,840
So now that we've done that we should be able to run this, and then that method will be called back.

118
00:09:12,680 --> 00:09:19,530
So let's try that, let's go into search and this time we'll close, and it correctly goes back to MainActivity as

119
00:09:19,540 --> 00:09:23,030
you can see. That's fantastic, cancelling a search now works,

120
00:09:23,160 --> 00:09:28,980
and that's our app just about finished. But there is one thing we should probably add. Now to show what that is,

121
00:09:29,230 --> 00:09:30,990
I'm going to see firstly, by doing a search,

122
00:09:30,990 --> 00:09:36,200
it there's any photos of blue monkeys driving Porsche cars in a hurricane.

123
00:09:36,390 --> 00:09:44,220
So I'm going to use a search term, blue monkey, Porsche, hurricane

124
00:09:48,170 --> 00:09:54,450
search, and not surprisingly we don't get any photos appearing. Now in that scenario,

125
00:09:54,770 --> 00:09:59,450
it would be nice to show some sort of message to let the user know that no photos matched the query,

126
00:10:00,140 --> 00:10:02,770
and that'll actually let them know that the app's still working.

127
00:10:02,900 --> 00:10:04,420
It hasn't failed in some way.

128
00:10:04,620 --> 00:10:09,050
Now the easiest way to do that is to modify the recycler view adapter,

129
00:10:09,200 --> 00:10:11,630
and we're going to have to get it to fib slightly.

130
00:10:11,900 --> 00:10:16,640
So I'm going to finish the video here, and in the next one we'll see why it's sometimes necessary to

131
00:10:16,640 --> 00:10:18,550
get your classes to tell lies.

132
00:10:18,560 --> 00:10:19,520
See you in the next video.

