Alright, so it's time to start creating our app to download the flickr feed and pass out the information
that we need, so we need to start a new project in Android Studio.
So I'm going to do that, and I'm going to call this one Flickr Browser. The company domain,
I'm going to have learn programming dot Academy as I've done for other videos in this course, and as
usual tick the box to include Kotlin support if you're using Kotlin, and leave it
unticked if you're using Java.
Click on next, and on this screen we're going to choose API 17 as we normally do,
we've done for other projects in this course, click on next. Now in the template screen here I've currently got
the choices that you can see on screen.
However keep in may that Google do change the templates from time to time, and the options you've got
available may be different.
And as I mentioned in the templates video in section 3, these are just templates that we can add and
remove code as needed.
So it makes sense to choose a template that best fits your application, and there should always be something
like the empty activity, that'll create a project with very little code filled in for you.
Now this app we're creating is going to use a menu, but we won't be using the floating action button because
you can see at the bottom of the basic activity template, this one here, basic activity has both a menu and
a fab, a floating action button, and you can see the menu at the top half here of the templates image.
Now I don't want both, but it's easier to remove code than go to the trouble of adding code for the menu,
back in. So basic activity is the one that we're going to use here.
Once again if you have different options in your version of Android Studio when you come to watch this
video, choose the simplest available template that includes a menu. So I'm going to click on next now that I've chosen
basic activity. I'm going to leave all these names at the moment as the default. While we're creating this
app I'm going to show you how to manually rename and change things anyway. So with that done I'm going to click on finish. We're going to wait
while Android Studio creates the project for us.
Alright so you can see we've just about finished, and our default application's being created,
and we should see two created layouts here, and I'll just expand up here so we can have a look, look in the res folder.
And we just need to give it a little bit longer to complete, and then we'll be able to see. Alright there we go. I can
see now that in our layout folder,
we've got activity main and content main dot xml, and we saw those in the template videos.
Now Google may decide to change that,
so if you only got a single layout xml file created that's fine.
Just make your changes in that one. OK now I want to add logging code to our app.
I mentioned this in the button counter app, in that section of the course, when we looked at the activity
life cycle, but I'm going to go over it briefly again here.
Logging when your methods start and end is one of the most useful techniques you can use when trying
to understand how the Android framework operates.
So I'm going to leave the user interface, the creation of that, until later.
We're going to start by downloading the data and then parsing it.
So we're going to be writing a lot of output to the log cat, so that we can check what's happening and
see that things are working.
Now this app will also be using an async task to perform the download on a separate thread. So that stops
the user interface from appearing to hang when a potentially long running task is going on.
Now it's a good idea to do things like downloading or reading lots of data from a file or database in
a separate thread.
In fact the http class, which we're going to use, will give an error if we try to download on the main user
interface thread.
Now messaging threads can be tricky but the async task does all the hard work for us.
So we're going to take a similar approach to the top 10 downloader app, but I'm going to be doing things
slightly differently when we come to use the data downloaded by the async task.
Now as I mentioned in the introduction, the app's also going to be using an adapter
when we come to display the data. Now the way all the various classes work together can take a while
to understand,
so what I'm going to do is log a message each time a method's called. Now the messages in the log will
then show what methods are being called, and when. This allows us to see what's happening,
and the order that things are being called. Now those log entries will make it much easier to understand
how the app works.
Now up until now we've used a private variable for the log tag.
So I'll start this app by showing you another way to define it, using something called a companion object.
Now Kotlin doesn't have a direct equivalent to Java's static variables but we can create something similar.
Now I'm going to add it to the end of our main activity class, so let's open that up, and down here before the last right
curly brace, I'm going to type companion, object and just press enter there.
OK like so, and then within the companion object we're going to type private const val, TAG in upper case, equals
double quotes MainActivity. So that's our companion object.
And then what we're going to do is come up to our onCreate method up here, and we're going to actually to use that.
So basically on the first line, before the super.OnCreate code, we're going to type Log dot d parentheses TAG
in uppercase, comma space, then onCreate in double quotes, called. OK we're also going to add the same thing, a log
entry to onCreateOptionsMenu and on items, onOptionsItemsSelected.
So I'm going to take a copy of that line, first line of the onCreateOptionsMenu, just put it in there. This time we'll
change it though, so it's onCreateOptionsMenu, and for the onOptionsItemsSelected,
we're going to put a Log.d before the return when, so that's onOptionsItemSelected called, as you can see. OK.
That's a fairly standard debug logging line that we've used a few times now.
So what I'm going to do is run this to make sure that it's working,
so we're going to start the app, and I'm going to start my emulator.
It's not started on this device, so I'll just fast-forward this one starting. OK,
there's our app running, and
if you go back to log cat, we should be able to see that output hopefully, and what I can do to make sure we
can actually filter on main activity, so let's try doing that, and there we go, main activity.
That's enough there, you can see we've got our two options at the moment, onCreate is being called, and on
CreateOptionsMenu has also been called. So what have we done differently, and perhaps more importantly,
why am I showing you this.
Well to answer the second question first, I'm showing you this because you're going to see it being used.
It's the code that'll be generated automatically, when you use Android Studio to convert Java code
to Kotlin for one thing.
Now I'm not going to show you how to convert Java to Kotlin yet, and that's mainly because it's too
easy just do that yet and end up not really writing Kotlin. But you'll see these companion objects
like we've created here, used for things like analog tag.
So it's important to be familiar with code like this, and again this code I'm talking about is the code on line 44.
Now Java has things called static fields, and these belong to the class rather than to the instances
of the class. Now don't worry too much about that.
We're working with Kotlin not Java after all, but one reason for using those static fields is that there's
only one copy created.
Now if we used a normal variable, each instance of main activity would create a new copy of the tag variable.
Now obviously that's not a good use of memory because each copy would contain exactly the same text,
and if we created 1000 instances of main activity, you'd have a thousand variables all with exactly the
same value,
the string main activity, so that's nearly 12K of ram used up, which is a bit of a waste to put it mildly.
So that's one reason for using class variables rather than instance variables.
Now the equivalent way to do that in Kotlin is to use a companion object, and declare tag
in this case, in there. Now unfortunately it's not exactly equivalent.
In fact because we've used const here on line 45, we end up with a tag being placed in line.
So that means the text is copied into our code, every where that we've used the tag variable.
Now that may not make much sense, so I'm going to convert the code to Java to show what's being
produced for us.
Now if you don't know Java, don't worry too much about the code we're about to see.
The point is to show you how our tag variable is really used where the Kotlin program is compiled.
Now converting Kotlin to Java is currently a two step process.
So first thing is the Decompile Kotlin to Java option, this is on the tools Kotlin menu,
Decompile Kotlin to Java, which is currently greyed. So it's basically not available yet,
but what we can do instead, is use the Show Kotlin Bytecode option to see what our Kotlin code compiles
to. So basically, tools, Kotlin, Show Kotlin Bytecode.
If I bring this over a little bit more, you can see all this strange code in the Kotlin Bytecode pane. Now there's very few
people on the planet who can understand this Bytecode.
Now I'm not going to attempt to make sense of it.
It's intended for the JVM to execute, not for humans to read, but what we can do is click the decompile
button to convert it back to Java.
So go go ahead and do that, and I'm going to close this window,
and this is the decompiled version converted back to Java.
Now this might look horrible, but if we scroll down and have a look we can see the Log.d calls
in each of the methods - Log.d again, Log.d and Log.d.
So notice that the string main activity is actually repeated in each of those calls, three times there.
That's what I meant by the tag value being placed in line. Now our attempt to save memory by using
the Kotlin equivalent of a static field hasn't worked out too well. Our
code's duplicating the value of tag, each time we do any logging. OK I'm going to close the decompiled Java tab here, and
I've already closed the Kotlin Bytecode pane. I'm going to go back to our code now on the screen. So you'll almost
certainly come across code that uses a companion object like we've used here.
But I'm going to suggest that you don't do it in your activities. So just to be clear I'm not saying
that you shouldn't use companion objects.
We're using them in some of our code and they do have their uses.
What I'm saying is that I wouldn't use one here.
Now one reason is, we're only going to have one instance of main activity anyway.
Well now we may create thousands of instances of some classes, such as the feed entry class in our Top
10 downloader. We created an instance of feed entry for each row in the list view.
So we definitely created quite a few of those, but it's very rare for an app to create several instances
of an activity at the same time,
so the benefit of a static field in saving memory doesn't really apply here.
Now if you're comfortable with Java, and want to check the decompiled code again for, after removing const
from line 45, you'll see why that's also not a good option.
So I'm going to comment out our companion object code anyway, rather than deleting it, so it's available for reference.
Now I've covered this now, because it's about now that you probably want to know about the lint boarding
when we declared tag as a normal variable.
So let's just come up here and do that first, right at the top, we're going to do it as the first entry inside the class, so private
val, TAG in uppercase equals, in double quotes MainActivity, and we get a weak warning that private property
tag doesn't match, so come over here, private property name tag doesn't match regex.
Now we're getting that warning because variable names should begin with a lower case letter. Constants
should be in all capitals and we're using tag as a constant,
but we haven't declared it to be one.
We've just seen why we don't want to do that, but it does mean we get this warning.
Now one way to remove this warning is to name tag in lowercase.
That's an option but not something we want to do,
if we're working with XML for example. There's all sorts of examples where we might want to refer
to tags, and using tag in lowercase for our logging would just cause confusion.
Now I don't actually have an answer for this.
The best solution I can think of would be to disable the lint check for this line of code, but unfortunately
that's not possible at the moment.
It is actually worth clicking on TAG, and then come over here and check it on the light bulb options, to see
if there's an option to suppress the warning in the future.
For now I'm just going to live with the warning.
Now that's not ideal but at the moment it's the best option we have available.
OK, so moving. Now as I mentioned previously we don't need the floating action bar code in the onCreate method. So,
that's because we're not using the floating action button in this app.
So I'm going to go ahead and delete that code, that's this code here from fab.setOn
ClickListener, and comment all that out, like so, and the other thing I'm going to do, is actually add a log entry for when the
method ends. So I'm going to do a Log.d after that, parentheses TAG comma double quotes onCreate ends.
So each time this onCreate function is called from now on, we'll see the message "onCreate called"
when the function starts, and "onCreate ends" when it finishes.
Now I'm not going to be including logging like this in every single function, but I will add it to the
interesting ones so that we can see the flow of the program when it runs.
Now Android Studio should also remove the fab imports automatically,
but if it doesn't, they'll appear in grey to show they're not being used. So scroll up to the top and have a look at our imports.
In my case you can see they've actually being removed, and I'll put this back just to show you what I mean.
And we can see how they're added automatically, and if I comment that out again, they're actually removed,
see the snack bar gets removed for us automatically in the imports. Well there's actually three, there's a floating action
button, a snack bar and then the Android.view.view, and
you can see that they've all, they're now no longer showing in the input section.
Alright so this video's got quite long. Our
basic project has been set up, so I'm gonna stop the video here, and in the next video we'll start looking
at downloading our json data. So I'll see you in that next video.