So we're well on the way to getting this app finished.
We just need some way now to pass the search results back to MainActivity.
Now a good solution here would be to use something called shared preferences. Now shared preferences provides a way
to store up data, so you can retrieve the data again next time the app starts up.
They're not as powerful as a full database, but for many applications where you don't have to store
a lot of data, they're ideal. And the other good thing is that they're also very easy to use, and they
work in a similar way to the bundles that we've used before.
So you store data in key value pairs, and retrieve the data items by specifying the key.
So I'm going to add the code now to the onQueryTextSubmit function in search activity, just so you
can see what it does.
So onQueryTextSubmit, we're going to add code after the logging,
and we'll start with val sharedPref equals PreferenceManager.getDefaultSharedPreferences, then parentheses,
and it's going to be applicationContext.
Then we're going to do sharedPref dot edit, we're actually calling the edit function, so there's parentheses dot putString
parentheses, and it's going to be flickr query
comma space query closing parentheses dot
apply. We're calling the apply function, and then we're going to do searchView question mark dot
clearFocus, and then we're going to leave the call to finish and then return true.
So what we're doing here is starting out on line 41. We're getting a shared preferences object by calling the Preference
Manager's getDefaultSharedPreferences function, passing it a context.
Now here we want to pass the application context rather than using this, because the date is going to
be retrieved by a different activity to the one that saved it.
Now SearchActivity will store the data and MainActivity will retrieve it.
Now we have to call the edit function on the next line, line 42, to put the shared preferences into a writable
state, and then we use the, we call the putString function to store the search query string.
Now we store the string using the flickr query constant that we defined in base activity as the key. Now
MainActivity and SearchActivity can both use the same constant, which ensures that they're both using
the same key when saving and retrieving the data, and the data's then installed when we call the apply function.
Now it's not obvious why we need to call clear focus in there,
and you wouldn't normally find out what problem it solves, unless you tested the app on a device with
an external keyboard.
Now fortunately our emulators
can use the PC's keyboard, so you can spot the strange behavior if we leave that out.
Now the problem it fixes, is if you type a search query, then use the keyboard's enter key to submit it.
Now when you do that the search icon in MainActivity
also receives a click event, and just launches search activity again.
And in fact you saw me do that in the previous video,
when I pressed enter, entering a search query before I ended up actually correctly pressing the arrow
down the bottom right hand corner.
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
the toolbar before returning to MainActivity.
And remember that you'll only see the different behavior when you press enter on an external keyboard. Alright so
to get the data back,
we just read the same key from the shared preference when main activity resumes.
So let's go back and edit the MainActivity onResume function, and put some code in there. So I'm going to
leave the call to super onResume. On the next line we'll do val
sharedPref is equal to, and its PreferenceManager.getDefaultSharedPreferences application context
again. Then we're going to do val query result is equal to sharedPref.getString parentheses, and it's going to be
flickr underscore query comma and two double quotes, closing parentheses.
Next we're going to write a bit of code here. We're going to put if parentheses queryResult
dot isNotEmpty,
and we'll just add a blank
code block for now. Then on the next line we're going to do some logging,
so Log.d parentheses TAG comma double quotes dot onResume ends.
So basically this is just the reverse of what we did to store the data.
So we're creating a shared preferences object on line 120, using exactly the same code actually,
then using the getString function to read the search string from the stored shared preferences on line
21. Now there's no point downloading
anything
if no search criteria was specified, so we're checking to make sure the query result string isn't empty
before attempting to download and parse the data.
Or at least that's the code we're going to be using when we start filling that out from line 24. The getString
function will attempt to retrieve the data stored with the key flickr query,
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
in this case. So that's what this second argument's all about.
Passing an empty string allows us to check to make sure we did get a search term from the user. OK.
So if the user did specify something to search for, then we just repeat the code in onCreate to
download the new data.
And in fact we don't need to repeat it.
We can just move that code into onResume.
Remember that onResume's called after onCreate.
So what I'm going to do is cut three lines from onCreate, and paste them into this empty if block in the
onResume function. So back to onCreate. So the three lines
that we want are these here,
val
url, the val getRawData and then the execute. So I'm going to copy those,
or cut those rather. I'll just clear that up a little bit. Then go down to the resume, the
onResume function.
I'm going to paste that in here.
So that's now called in the onResume function.
And again, just to repeat, onResume's called after on Create.
So therefore by putting it in onResume, we still guarantee that this code is going to be executed.
Alright, so at this point all that remains to do, is to pass query result to the Create uri function, instead
of the hardcoded string Android Oreo that we've currently got over here.
So let's do that. Let's get rid of this, remove the hardcoded string there,
and we're going to replace that instead with queryResult.
Alright so that should work now,
so let's test it.
Now this time when I ran the app there's no data displayed, but that's because there wasn't any shared preference
data to retrieve.
So we have to do a search before we get any photo's returned. I'm going to go ahead and search for marshmallow
again.
And success as you can see there. We've got a load of photo's tagged now with marshmallow.
Now we can narrow that down a little bit by searching for Android marshmallow.
So let's try that, android comma marshmallow,
and you can see we're getting some different results based on that as well,
not particularly appropriate to Android marshmallow
so let's just try another one to make sure.
We'll try android
nougat,
and we've got some more computer related results there, android nougat showing. So clearly that's working fine.
Alright.
So that's great,
but what happens if a user decides that they don't want to search though, and clicks the X to cancel.
Let's try that.
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.
It's closed the search view but it doesn't return to MainActivity.
But we saw, if you recall, an onClose function in the documentation, so we can implement that listener
and call finish if the user closes the search view instead of submitting a search.
So let's go ahead and create that, or add that rather, to the onCreateOptionsMenu function in Search
Activity.
We want to add it down here, before the closing onCreateOptionsMenu
log entry, so add it there.
Let's add a bit of space.
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
there is finish and then false.
So now that we've done that we should be able to run this, and then that method will be called back.
So let's try that, let's go into search and this time we'll close, and it correctly goes back to MainActivity as
you can see. That's fantastic, cancelling a search now works,
and that's our app just about finished. But there is one thing we should probably add. Now to show what that is,
I'm going to see firstly, by doing a search,
it there's any photos of blue monkeys driving Porsche cars in a hurricane.
So I'm going to use a search term, blue monkey, Porsche, hurricane
search, and not surprisingly we don't get any photos appearing. Now in that scenario,
it would be nice to show some sort of message to let the user know that no photos matched the query,
and that'll actually let them know that the app's still working.
It hasn't failed in some way.
Now the easiest way to do that is to modify the recycler view adapter,
and we're going to have to get it to fib slightly.
So I'm going to finish the video here, and in the next one we'll see why it's sometimes necessary to
get your classes to tell lies.
See you in the next video.