Alright, so the content resolver that we started talking about in the end of the last video, will execute
our query against its data source and give us back a cursor. And then we we can then use the cursor just
like we've done in previous videos.
We'll just end up using a loop to loop through all the rows in the cursor, and then to display the contact
names. So that bit's easy,
but what's this ContentResolver all about.
Let's talk about that in a bit more detail.
So to explain about the various classes that are used when we access data using a ContentProvider, let's
consider some cooks who need milk and eggs for whatever they're going to be cooking today.
Now to get their ingredients for their meal, they're going to go to their local shop to buy milk and eggs.
Now the shop uses a number of suppliers.
They may send someone to the farmers market very early in the morning, or the goods might be delivered
by huge trucks overnight
in the case of modern supermarkets.
But however they do it,
they can provide mild and eggs when a customer asks for them.
Now I've simplified this of course, because modern supply chains tend to be quite complex.
But the shop supplies ultimately get their milk and eggs from a farm.
So the slide here shows the flow of food from the source - so the cows and chickens, who are the source of
the milk or the eggs - to the farmers market.
Now the farmers market supplies the shop with the goods, and the shop in turn, passes it on to the customer -
our cooks in this example.
Now I guess the analogy falls down a bit because the milk and eggs only go in one direction; from the
source to the suppliers, then to the shop and finally to the customers.
In the case of data being retrieved from a data source, we can obviously store data in the database as
well as taking it out.
But if we ignore the fact that you wouldn't try to put an egg back into a chicken, this maps quite nicely to what
we're doing with our ContentProvider and ContenResolver.
So let's see how they fit into all of this.
Alright.
So data is requested by a client,
and that's a commonly used term in computing for some class or process that requests either data or a service
from something else.
So here the client is the cooks, and they're requesting ingredients from the shop.
Now in our case, in an Android program, the client may be an activity or a loader.
Now in the example we're working on, the client is MainActivity as that's what's attempting to retrieve
the Contacts data.
Now Main Activity requests the data at once from a ContentResolver, and that's performing the role
of the shop in our diagram.
Now in the same way that the cooks don't have to know where the milks and eggs are coming from, MainActivity -
the client here - doesn't know where the ContentResolver will be fetching the Contacts data from. So Main
Activity specifies the kind of data it wants - Contacts data
in this case - in the same way that the cooks specify whether they want milk or eggs.
So it's the job of the shop to get the milk from wherever it gets milk from, and to get eggs from wherever
it gets eggs from.
In other words they don't have to both come from the same place.
The key thing here is that when the customer asks for milk, the shop knows where milk comes from.
Now if the customer asks for eggs, this is a different request
and the shop needs to go to the egg supplier rather than its milk supplier. In the same way,
it's the job of the ContentResolver to get the Contacts data from whoever, or wherever it needs to get
it from.
Now if we'd asked the ContentResolver for phone log data instead, it would then go off to a different
place - a different supplier or in this case - to get the phone log data.
Where it goes to get the data is to a ContentProvider.
Now we can see here, there are two ContentProviders. One supplies milk and the other suppliers eggs.
So depending on what the customer requests,
the shop can go off to the appropriate supplier to get it.
Now it's the same when MainActivity requests contact data from the ContentResolver.
So MainActivity uses the URI to specify the kind of data that it wants. The Content
Resolver then uses the URI to decide which ContentProvider it should ask to supply the data.
Now we're going to be looking a bit more at the mechanisms behind this.
At the moment though, we're just seeing how it all fits together.
So one important thing here is that the ContentResolver doesn't know where the ContentProvider will
get the data from. And there's no reason why it should, because it just requests the data and expects
it to be delivered.
The actual details of how the data's collected, and from where, is irrelevant.
Now in the same way that the store - or shop - doesn't need to know which farms the suppliers get the
milk and eggs from
Now the ContentProvider fetches the data from its data source.
So the milk ContentProvider goes to the cows to get milk, and the eggs ContentProvider goes to the
chickens for eggs.
In our app, the Contacts ContentProvider goes to the Contacts database to get the contacts records that have
been requested.
So you can see that there's quite a bit of obstruction there -
but there is in modern shopping habits too.
So it's not essential that we have supermarkets and suppliers and so on.
We could all go directly to the farms if we wanted to to get our milk and eggs there.
But if you think about it that would be terribly inefficient, though.
So as populations increased and people started living in cities, we started to get layers of abstraction
added to the way we shop for food.
But going back far enough in time, people may have had their own cow and their own chickens.
But then it became more efficient for some people to look after the animals, while others became blacksmiths
or house-builders or whatever.
So now the blacksmiths and the builders are abstracted from the source of their food.
As the population grew, suppliers collected the milk from farms in the country and supplied the
shops in the towns and cities. so that's more levels of abstraction. Now terms like levels of abstraction
or abstracting data can sound very confusing,
but this is all that they really mean. When the consumer of data is separated from the source of that data,
then that's abstraction. The more things there are between the consumer and the source, the more levels
of abstraction there are.
So that's how the ContentResolver fits into our attempt to access the Contacts data.
Now the Content Resolver provides a layer of abstraction between our app, which is the client, and the
Content Provider. The Content Provider adds another layer of abstraction on top of the underlying
data source.
An application has a single ContentResolver that provides access to all the ContentProviders
that exist on the Android device.
And that's why we used getContentResolver rather than creating a new one, because there is only one, and
it holds a list of all the Content Providers that are registered on the device.
Now the Content Resolver uses something called an Authority that's included in the URI to decide
which Content Provider to direct data requests to.
Now we'll have a look at what an Authority is when we create our own Content Provider later.
The important thing is that there's a mechanism that the client can use to let the Content Resolver
know what it wants, and the Content Resolver uses that to decide where to go for the data.
Alright so that's how it all fits together.
I'm going to finish this video here now.
In the next video let's go back and finish off the code and retrieve the contacts, now that we've got
a good understanding of, hopefully got a good understanding of the Content Provider and also how this Content
Resolver works.
So I'll see you in the next video.