Alright so the Tasks Contract Class is
a topic for this video. Now when we used
the Content Provider in the previous app,
we didn't know what the real columns in
that database were called. In fact, we
didn't even know that the data was
coming from a database. The Content
Provider abstracts the underlying data,
and prevents a standard interface that
we used to access the data we want. Now
if you remember we use constants to
refer to the actual fields. So our
Content Providers are going to allow the
same thing, so we'll start by creating a
Contract Class to define the names that
are used to access our data. Now Google's
Contacts Contract class uses an
interface to provide the column name
constants. You can find a lot of argument
on-line about whether using an interface
just to provide constant values is a
good thing or not. In this case, I think
using an interface in a Contract class
is perfectly valid. The fact that we're
talking about a Contract here, is an
indication that an interface is a
suitable way to implement this. An
interface is a Contract and guarantees
that it'll always provide the fields
and methods that it publishes. However,
Kotlin provides another way - Objects. So
you can find more information on Object
declarations in the Kotlin documentation.
I'm just going to briefly bring that up -
that's a good resource link to check out.
But one important use is to implement
the singleton pattern. If you only ever
want to have a single instance of
something, then an object in Kotlin may
be a good way to do that.
It does however have one limitation; you
can't pass arguments to its constructor,
but actually we don't need to do that
here. If you put an object inside a class
it becomes a companion object, which
we've looked at earlier. Now that's also
documented on this page, just after this
section - you can see the discussion there
about Companion Objects. Okay so I'm
going to use objects for the Contract
classes for our app. So I'm going to go
back to IntelliJ, and what I'm going to
do is create a new Kotlin class. So I'm
going to go to our package, right click
New
Kotlin File/Class, and we're going to call this
one TasksContract. Now creating an
object is very similar to creating a
class - we just used the word object
instead. So I'm going to type object
TasksContract, then left and right
curly braces. Now we'll start with a
string to store the table name. We'll be
referring to our table in a few
different places, so this is a good place
to define the name of the table. Now
remember that external apps don't have
to know anything about how we're
implementing the underlying storage,
which means the name of our table should
only be visible inside our package. So
I'm going to use the internal access
modifier to achieve that. So we're going to
type internal const Val TABLE
underscore NAME equals Tasks in double quote,
double quotes rather. Now note that we
can use the const keyword inside an
object - something we couldn't do in a
class. Alright so that's the table name.
Next we need to figure out our column
names. Now what we'll do is we'll put
them inside another object, in the Tasks
Contract object. Now this is effectively
the same as a companion object but we
don't need the companion. Now I'm going to
type it anyway, and we'll see what
Android Studio's link checker has to
say about it, and I'll just put a comment
down here, "Tasks fields". If we type companion
object Columns left and right curly
braces, we get an error there, and if we
have a look at the error: "Modifier
companion is not applicable inside
object". And so we can delete the word
companion near the keyword and just
declare an object, and I'll add the
constants for the field names inside
this object. We'll start with const val ID
in uppercase equals double quotes
_id. Then on the next line,
const val, in uppercase TASK underscore
NAME equals name double quotes. Next line
const val
Tech, TASK rather underscore
DESCRIPTION, in uppercase again, equals
and in double quotes Description. And
lastly, const val TASK_SORT
underscore ORDER is equal to SortOrder,
capital S, capital O there, in double
quotes. And obviously you can see, I've
capitalized the Name, Description and
SortOrder on lines 14 through 16.
So our columns object behaves almost
exactly the same as if it was defined in
its own column.kt file. The only
difference is that we can't refer to it as
directly as columns. We have to use tasks
Contract.columns. Now one advantage of
this, is that we can have several columns
objects. Now we're going to need to
define the columns for our Timings table,
and that object would be referred to as
timingsContract.columns. Alright, so
this can, this columns object is
just to provide the constants we'll be
using to refer to the column name in our
Tasks table. So we're going to add more
code to this TasksContract object later,
to provide everything that we'll need
for our Content Provider, but that's
enough for now, except there's one change
that I want to make. And I want to make a
change to our code so that we can have a
look at what Base Columns is. So if we
come down here and change the ID, I'm
actually going to add the word Base
Columns, BaseColumns._ID and
I'm going to delete out the double
quotes _id that we had
there. So if we click on this now we can
check out the source code, and you can
see there that BaseColumns is an
interface that defines two constants:
underscore ID and underscore COUNT. Now I
mentioned that Android makes use of a
primary key called underscore ID, and
this is where that name's defined. Now we
could have left it hard-coded in our
code, but if Google provide a constant to
use, then we really should use that
constant. So that way, if they change
things in future our code will still
work and won't break. Now I can't really
imagine any reason why they might decide
to rename this field - it could break too
much existing code for one thing. So if
you prefer to
used the string literal underscore ID - I'll
just close this down - in your code instead of
BaseColumns._ID that
we've got here, that's probably fine. But
I've done it this way, because you'll see
this BaseColumns interface being used
like this in a lot of code on the
Internet
Alright so that's enough to be getting
on with. In the next video we'll start
looking at creating the database class.
So I'll see you in the next video.