使用SQLite和多个表创建自己的ContentProvider

11
我正在阅读实现自己的ContentProvider与SQLite一起工作的教程,在ContentProvider.query中有几个问题令我困惑。它似乎非常硬编码只针对一个表(教程中的todo表),但也许是我没有理解?如果我想查询另一个表,比如nodo,我该如何更改ContentProvider?
我应该在queryBuilder.setTables(String inTables)中以某种方式追加表名称吗?
那CONTENT_TYPE和CONTENT_ITEM_TYPE呢?每个表都需要吗?
TODO和TODO_ID变量以及查询方法中的switch怎么样?
看起来我需要有很多if / switch条件来支持具有相同ContentProvider的多个表,这是正确的方法还是错误的方法?
谢谢
Søren

  1. setTables... 如果需要连接表,则取决于您的需求,但仍然要遵循第2点...
  2. Content mime... 是的
  3. 对于每个表都要再次执行。
  4. 错误的路径... 不是,我认为这是一个好路径... 您可以尝试搜索/编写某种生成器 fx http://selvin.pl/autocontent.zip <= 这是我的,但它目前仅支持表而不是视图。
- Selvin
3个回答

27

现在如果我想查询另一个表,比如nodo,我该如何更改ContentProvider?

查询新表意味着你需要添加一个新的Uri,因为Uri选择数据源,类似于使用不同的表。

你需要将已经存在于todos中的所有硬编码值都添加到你的其他表中。例如:

// ------- 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);
  }

我应该在queryBuilder.setTables(String inTables)中以某种方式附加表名吗?

是的,如果不同的Uri从不同的表中读取,则根据Uri匹配设置表。

CONTENT_TYPE和CONTENT_ITEM_TYPE呢,每个表都需要一个吗?

这取决于实际的内容类型。如果它们不同,并且您需要一个类型,则需要创建一个。但您甚至不需要拥有它们。该示例定义了它们,但甚至未使用它们。需要在getType中返回类型,请参见文档

TODO和TODO_ID变量以及查询方法中的switch怎么样?

这些是为UriMatcher定义的常量,在此处得到了很好的解释。它基本上简化了字符串匹配。一个大的ContentProvider可能有100个不同的Uri,在query中选择正确的表格将非常痛苦,如果您必须编写if (uri.getPath().equals("todos") { /* code */ } else if (uri..一直写下去。


你好,你会如何在这种情况下实现删除方法?能帮忙吗? - JoaoFilipeClementeMartins

1
这里是解决方案,使用UriMatcher,您可以在内容提供程序中实现多个表格。

0

内容类型和内容项可以如下所示,并且它们可以分别包装在每个表的单独类中

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'

这定义了一般的内容类型 `vnd.android.cursor.item/vnd.anthingasabove.table' 这还定义了具体的内容类型,并且对于任何应用程序,这些字符串(单词)vnd.android.cursor.dir和.item必须是这样的,并且/vnd.之后必须是这样的

在扩展ContentProvider的类中,您只需使用相同的UriMatcher实例来映射表格


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接