I am reading this tutorial on implementing my own ContentProvide for working with SQLite. Int the ContentProvider.query there are a few thing that puzzles me. It seems very
Content type and content item can be as follows and they can be wrapped in a separate class for each table
public static final String GENERAL_CONTENT_TYPE = "vnd.android.cursor.dir/vnd.myfirstapp.db.member" ;
public static final String SPECIFIC_CONTENT_TYPE = "vnd.android.cursor.item/vnd.myfirstapp.db.member" ;
`vnd.android.cursor.dir/vnd.yourownanything.anything.tablename'
this defines the general content type `vnd.android.cursor.item/vnd.anthingasabove.table' this also defines the specific and it is constant to any app those strings(words) vnd.android.cursor.dir and .item must be like that and after /vnd. must be like that
and in the class that extends contentprovider you just uset the same instance of UriMatcher to map the tables
Now if I wanted to query another table, lets say nodo, how would I change the ContentProvider?
Querying a new table would mean that you need to add a new Uri
, since the Uri
selects the datasource, similar to using a different table.
You would be adding essentially all the hardcoded values that are already there for the todos for your other table. For example:
// ------- usually the same for all
private static final String AUTHORITY = "de.vogella.android.todos.contentprovider";
// ------- define some Uris
private static final String PATH_TODOS = "todos";
private static final String PATH_REMINDERS = "reminders";
public static final Uri CONTENT_URI_TODOS = Uri.parse("content://" + AUTHORITY
+ "/" + PATH_TODOS);
public static final Uri CONTENT_URI_REMINDERS = Uri.parse("content://" + AUTHORITY
+ "/" + PATH_REMINDERS);
// ------- maybe also define CONTENT_TYPE for each
// ------- setup UriMatcher
private static final int TODOS = 10;
private static final int TODO_ID = 20;
private static final int REMINDERS = 30;
private static final int REMINDERS_ID = 40;
private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
sURIMatcher.addURI(AUTHORITY, PATH_TODOS, TODOS);
sURIMatcher.addURI(AUTHORITY, PATH_TODOS + "/#", TODO_ID);
sURIMatcher.addURI(AUTHORITY, PATH_REMINDERS, REMINDERS);
sURIMatcher.addURI(AUTHORITY, PATH_REMINDERS + "/#", REMINDERS_ID);
}
//@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// Using SQLiteQueryBuilder instead of query() method
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
int uriType = sURIMatcher.match(uri);
switch (uriType) {
case TODO_ID:
// Adding the ID to the original query
queryBuilder.appendWhere(TodoTable.COLUMN_ID + "="
+ uri.getLastPathSegment());
//$FALL-THROUGH$
case TODOS:
queryBuilder.setTables(TodoTable.TABLE_TODO);
break;
case REMINDERS_ID:
// Adding the ID to the original query
queryBuilder.appendWhere(ReminderTable.COLUMN_ID + "="
+ uri.getLastPathSegment());
//$FALL-THROUGH$
case REMINDERS:
queryBuilder.setTables(ReminderTable.TABLE_REMINDER);
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
Should I append the table names somehow in queryBuilder.setTables(String inTables)?
Yes, if different Uri
s read from different tables then set the table based on the Uri match.
What about the CONTENT_TYPE and CONTENT_ITEM_TYPE, should there be one for each table?
Depends on the actual content type. If they are different and you need a type yes. But you don't need to have them at all. That example defines them but doesn't even use them. It would need to return the type in getType
, see documentation.
That about the TODO and TODO_ID varibles and the switch in the query method?
Those are constants defined for the UriMatcher
which is explained nicely here. It's basically a simplification for String matching. A big ContentProvider
can have 100 different Uris and selecting the right table in query
would be painful if you would have to write if (uri.getPath().equals("todos") { /* code */ } else if (uri..
all the way.
Here's solution to your question, using UriMatcher, you can implement multiple tables in a content provider.