G'day everyone, welcome back.
One of the neat things that Kotlin lets us do, is to add
functions to existing classes without modifying the class. It does this using
extension functions. Let's have a look at the onBackPressed function in Mainactivity.
In there we call the showConfirmationDialog function, just as
though it was a function of the activity. In fact, it now is a function of the
FragmentActivity class. We've extended the class without having to change its
source code. We could do the same thing by creating a subclass of FragmentActivity,
but extension functions save us from having to do that. The showConfirmationDialogue function
is available in any fragment activity that
we add to our app. It extends the FragmentActivity class because we've
specified that when declaring the function. That's why we've got Fragment
Activity dot before the function name, in extensionfunctions.kt. When you
create an extension function, it's receiver is the instance of the class
you call it on. Talking about a receiver like this, which you'll see in the Kotlin
documentation, just means that the function automatically gets this. I'll
demonstrate that quickly. This is a course on Android development, not on the
Kotlin language, so I'm not going to go into great detail, but it's useful to
understand the basics of these extension functions. I'll start by deleting
FragmentActivity from the function declaration. That gives us an error when
we attempt to get the supportFragmentManager.
We're attempting to call the getSupportFragmentManager
method of the FragmentActivity class, but we don't
have an instance of the class to call the method on. I said method there,
deliberately, because the FragmentActivity class is written in Java.
We access supportFragmentManager as if it were a property, because Kotlin lets us
use that syntax, but behind the scenes, it's using a Java method call.
Okay, I'll undo that change to clear the error. Just in case that didn't make
sense, what we're really doing, is this.
We don't need to use this there. I've just
done it to show that we do have an instance of FragmentActivity inside our
extension function. Alright let's create a few more extension functions.
Looking at MainActivity, we have to get a supportFragmentManager,
in order to call findFragmentById, and we do that in quite a few places.
We'll see them in a moment. First, I'll simply create an extension
function to simplify that. I'll add it to the start of this file, before the
showConfirmationDialog function.
Remember to import from Android X if you are prompted for the import.
The fragment may not exist, so we return a nullable Fragment type. Okay, let's see
how that can clean up the code in MainActivity.
The next place is in onSaveClicked.
In fact, we could get rid of the fragment variable there.
We've got another call in onOptionsItemSelected.
There's another one in onBackPressed,
and the last one is in onPositiveDialogueResult.
Alright, that's all a little bit cleaner but it's hardly earth-shattering, but we can do
more. Fragments are a bit messy to manipulate, as we can see from the code
in the taskEditRequest function.
In there, we have to get a reference to the
supportFragmentManager, then call its begin transaction function to start a
fragment transaction. Inside the transaction, we replace the fragment with
a new one, and have to remember to call commit. Forgetting to commit the
transaction is easily done and means the new fragment won't be shown.
Wouldn't it be nice if we could just call a replaceFragment function, something like ...
That looks a lot cleaner and would avoid the possibility of forgetting to commit the
fragment transaction. We can do that by creating a replaceFragment extension
function. The function would still be slightly complicated, but it can be
simplified even further by creating another extension function on the
FragmentManager class. In fact, someone's already done that. Dinesh Babahunky
posted an article on medium. I'll paste some code that's based on that article
after the other extension functions.
We'll start with a comment; 1, because it's good to acknowledge other people's work,
and 2, it means that if we ever come back to our code, we'll know where
we got it from.
If you're prompted for the imports, remember to choose the Android X libraries.
We've migrated the app to Android X, and you shouldn't mix Android X with the old
support libraries in the same app. You may also have to delete some unused
imports manually. Check out Danesh's article for a description of how these
functions work. The inTransaction functions differently to the early code
in Danesh's article because he improved it later, as a result of comments on the article.
Alright, back in MainActivity, that's fixed the error in the taskEditRequest function.
Scrolling back up to the removeEditPane function,
that's easier to read and once again, removes the risk of forgetting to commit
the transaction. Okay that's a quick look at how extension functions can help to
make your code more readable and also more reliable. I'll stop this video here,
but remember to test the app to make sure our changes haven't broken anything.
We'll continue with the dialogues because we've still got the About
dialogue to add, and also a dialogue for the app settings. In the next video, we'll
take a break from coding and look at how to add an app icon to the app.
We're doing that now because we'll also need the icon for the About dialogue.
See you in the next one.