Alright so let's talk about the App
Database class. So in the previous video
we created a Tasks Contract class that
defines the column names for our Tasks
table. Now that might seem a little bit
over the top just to declare a few
string constants, but as we create more
code you'll see why we've bothered
creating this. In this video we'll create
the database class that will handle
creating our database. And it'll also
provide the database object that our
Content Provider is going to need when
it comes to access the database. So let's
start by creating the App Database class.
I'm going to right click on the package,
New, Kotlin File/Class and AppDatabase
being the name. Now I'm going to make
this internal, because the only thing
that should ever use this class will be
our Content Provider. I'm going to type
internal class AppDatabase, left and
right curly braces. In fact, what I'll do
is, I'll add a comment to that effect at
the start of the class. I'm going to add
it here and we're going to say "Basic
database class for the application." and
"The only class that should use this is
Approvider",
and Approvider's going to be in left
and right square brackets.
And notice how that got highlighted when
I typed that in left and right square
brackets, but more on that
in a moment. So when you start a comment
with a forward slash and two stars or
two asterisks, that indicates what's
known as a doc comment - also known as a
KDoc. And it's very similar to the
Java doc comments, but some things such
as links have been simplified. Now you
may have noticed this type of
comment in the Android Java source code
that we've looked at. There's quite a
formal structure to these doc comments,
and you may have noticed this when we
looked at documentation previously in
this course for a method slash function.
So the content looks like a formatted
version of the comments in the source
code, and there is a reason for that.
That's because the documentation is
generated from those comments using the
Java doc tool. Now in Kotlin the same
applies but, the tool's called Dokka. Now
I won't be discussing doc comments in
this course, but I'll start using them to
comment some of the code that we write.
Now you find loads of information
on-line, including the Kotlin
documentation. Let's go and check that out.
So this here you can see, that's
information about documenting Kotlin
code. And actually I planned to show
you this KDoc appearing when we used
the AppDatabase class in our code,
but unfortunately the Dokka plug-in for
Android studio is currently broken.
Hopefully they'll fix it soon, but as of
the time I'm recording this video, it
causes the Gradle builds to
crash which means that you can't compile
and run your apps. That's pretty severe,
so for that reason we're not going to
use it. So although we can't see it
working, it's still a good idea to
include doc comments in your classes. So
I'll just switch back to Android Studio.
Now these KDoc strings
are parsed by Android Studio, and
we've actually got a warning over here. We can
see if we hover over this AppProvider
in square brackets, and also the warning
over here in the gutter that we can't
resolve - symbol AppProvider. That's
because it hasn't been written yet, so
don't worry about that warning at the
moment. Alright but getting back to this
class, this AppDatabase class will
extend
the SQLiteOpenHelper class that
Android provides to make using sqlite
databases easier. So let's go
ahead and add that -
so the colon after the AppDatabase space
and SQLiteOpenHelper parentheses.
Now we've got some errors at the moment.
The SQLiteOpenHelper class has
some abstract methods that we need to
implement. It's got no idea whether, or
what the structure of our database
should be, for example, so it leaves it up
to our class to implement the onCreate
function. But before implementing that
function and also the onUpgrade
function, there's another error because
the SQLiteOpenHelper class needs
some arguments in its constructor. You
can see when I hover over to that
warning, or that error rather, that
makes it clearer that we need to do
that. So it needs some arguments to
its constructor. So those are a context -
the name and version of our database - and
also something called a CursorFactory.
Now the database name and version can be
declared as constants, and I'll also add
a constant tag for logging, so let's go
ahead and do that. I'll add those above
the class definition here, so private
const Val TAG is equal to, in double
quotes, AppDatabase. Then next we've got
private const Val DATABASE underscore
NAME in uppercase, which unsurprisingly
is our database name. That was Task
Timer.db, and we also want a
const for the version; private const
val DATABASE_VERSION, again in
uppercase, equals 3. And now that
we've done that we can expand on the
class definition line on line 19.
So let's first add a constructor for App
Database - so after the AppDatabase type
constructor. Then in parentheses we're
going to type context in lower case,
colon Contexts with a capital C,
which is using the Android, or coming
from android.content. And if we scroll up
we can see now that import has
been added.
Then over to the right for the
SQLiteOpenHelper, we need to pass those
parameters now. So the
first one is going to be context - let's
add that. Next we want to pass the
DATABASE_NAME. Next we're going to pass a
null and I'll talk about that shortly -
the CursorFactory - and lastly the
DATABASE_VERSION. So that's fixed
one of those errors now, and if we hover over
here now, it's now just complaining about
the fact we haven't implemented the
methods. Alright, so what we've done
here, is when our AppDatabase instance
is created it'll be passed a context
now. That's needed as the first argument
in the SQLiteOpenHelper
constructor, which we've now added. The
DATABASE_NAME as the second argument is
obvious, and we'll see why we need a
version later which was the fourth
argument, later in the course. But for the
CursorFactory - the third argument - I've
specified null. You can create your own
class to create custom cursors if you
wish, and one reason for doing that is if
you wanted to log the SQL queries
before they're executed. for example. But
the Cursor class included in Android is
fine, so we're just passing null for that
third argument so that we can use that.
Alright, so at this point I'm going to
do something slightly strange now, and I
don't recommend you doing this in
production code. For reasons that will
become apparent shortly, it'll be useful
to see when a new instance of this class
is created. To do that, what I'm going to
do is add an init block that does
nothing more than log when it's called.
And that's going to be very useful for
us to see what's going on, but as I
mentioned isn't a good idea to use in
your apps. So we're going to go ahead and
add this init block, so it's an init, then add a left
and right curly brace. Then within there
we're just going to add a log - so Log.d
parentheses TAG comma, then in double quotes
AppDatabase colon initializing. OK. Now
we've still got that error because we
haven't implemented those abstract
classes, so let's get Android Studio to
generate those for us. So we'll implement
both onCreate and onUpgrade. Now
the SQLiteOpenHelper class can do
a lot for us, but it can't know the
SQL commands that are
needed to create our database, nor how to
upgrade it from one version to another.
So in other words we have to provide the
implementation of those two methods, and
that's why they're abstract in the
SQLiteOpenHelper class. Alright, so
we've implemented at the moment, empty
versions of both of those that have
only got a TODO in there. And when an
instance of this class is created, the
code in its superclass - which is
SQLiteOpenHelper - will check to see if
the database already exists. Now if
it doesn't exist, our onCreate function
will be called. Now this is where we'll
execute the SQL statements to create
the tables, views and other objects in
our database. At the moment though, we're
focusing on the Tasks table, and we
created the SQL for that in the
previous video. So I'm just going to paste
that in as a comment, so we've got a
reference point for the SQL code we're
ultimately going to be creating. Alright,
and I'll just delete the TODO there.
We'll paste that in as a comment. Alright,
so what we're going to do next is build
up the necessary string to create this
SQL statement, but let's work on that
in the next video.