自己的ContentProvider使用SQLite和多个表自己的、多个、ContentProvider、SQLite

2023-09-13 00:30:03 作者:哥的霸气,你是学不来的

我在读关于实施我自己ContentProvide与S​​QLite的工作本教程。诠释了ContentProvider.query有几件事令我费解。这似乎很难coded到只有一个表(本教程中的待办事项表),但也许我只是没有得到它?现在,如果我想查询另一个表,可以说NODO,我将如何改变ContentProvider的?

我应该在queryBuilder.setTables(字符串inTables)莫名其妙地追加表名称?

怎么样的CONTENT_TYPE和CONTENT_ITEM_TYPE,应该有一个用于每个表?

这对TODO和TODO_ID可变因素和查询方法开关?

看来我需要有很多,如果/开关条件,支持具有相同的ContentProvider多个表的,这是要走的路还是我在错误的道路?

感谢您 瑟伦

解决方案   ContentProvider

现在,如果我想查询另一个表,可以说NODO,我将如何改变ContentProvider的?

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

您将加入基本上所有的硬codeD中已经存在的待办事项为你的其他表值。例如:

  // -------通常是相同​​的所有
私有静态最后弦乐管理局=de.vogella.android.todos.contentprovider;

// -------定义一些尤里斯
私有静态最后弦乐PATH_TODOS =待办事项;
私有静态最后弦乐PATH_REMINDERS =提醒;

公共静态最终乌里CONTENT_URI_TODOS = Uri.parse(内容://+ AUTHORITY
    +/+ PATH_TODOS);
公共静态最终乌里CONTENT_URI_REMINDERS = Uri.parse(内容://+ AUTHORITY
        +/+ PATH_REMINDERS);

// -------也许还定义CONTENT_TYPE每个

// -------设置UriMatcher
私有静态最终诠释TODOS = 10;
私有静态最终诠释TODO_ID = 20;
私有静态最终诠释事项注= 30;
私有静态最终诠释REMINDERS_ID = 40;
私有静态最后UriMatcher sURIMatcher =新UriMatcher(UriMatcher.NO_MATCH);
静态{
  sURIMatcher.addURI(权威,PATH_TODOS,TODOS);
  sURIMatcher.addURI(权威,PATH_TODOS +/#,TODO_ID);
  sURIMatcher.addURI(权威,PATH_REMINDERS,提醒);
  sURIMatcher.addURI(权威,PATH_REMINDERS +/#,REMINDERS_ID);
}

// @覆盖
公共光标查询(URI URI,字符串[]投影,串选择,
        的String [] selectionArgs两个,串排序顺序){

    //使用SQLiteQueryBuilder而不是query()方法
    SQLiteQueryBuilder QueryBuilder的=新SQLiteQueryBuilder();

    INT uriType = sURIMatcher.match(URI);
    开关(uriType){

        案例TODO_ID:
            //添加ID发送给原始查询
            queryBuilder.appendWhere(TodoTable.COLUMN_ID +=
                    + uri.getLastPathSegment());
            // $落空$
        案例TODOS:
            queryBuilder.setTables(TodoTable.TABLE_TODO);
            打破;

        案例REMINDERS_ID:
            //添加ID发送给原始查询
            queryBuilder.appendWhere(ReminderTable.COLUMN_ID +=
                    + uri.getLastPathSegment());
            // $落空$
        案件提点:
            queryBuilder.setTables(ReminderTable.TABLE_REMINDER);
            打破;

        默认:
            抛出新抛出:IllegalArgumentException(未知URI:+ URI);
  }
 

  

我应该在queryBuilder.setTables(字符串inTables)莫名其妙地追加表名称?

是的,如果不同的乌里■从不同的表中读取,然后基于URI匹配表中设置。

  

怎么样的CONTENT_TYPE和CONTENT_ITEM_TYPE,应该有一个用于每个表?

取决于实际内容类型。如果它们是不同的,你需要一个类型是的。但你并不需要他们的。这个例子定义了他们,但甚至不使用它们。这将需要返回类型的getType ,见documentation.

  

这对TODO和TODO_ID可变因素和查询方法开关?

这些都是为 UriMatcher 这是很好解释的此处。这基本上是一个简化的字符串相匹配。一个大的的ContentProvider 可以有100个不同的URI和查询选择合适的表将是痛苦的,如果你会写如果(uri.getPath()。等于(待办事项){/ * code * /}否则,如果(URI .. 一路。

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 hardcoded to just one table (the todo table in the tutorial), but maybe Im just not getting it? Now if I wanted to query another table, lets say nodo, how would I change the ContentProvider?

Should I append the table names somehow in queryBuilder.setTables(String inTables)?

What about the CONTENT_TYPE and CONTENT_ITEM_TYPE, should there be one for each table?

That about the TODO and TODO_ID varibles and the switch in the query method?

It seems I need to have a lot of if/switch conditions to support multiple tables with the same ContentProvider, is this the way to go or am I on a wrong path?

Thank you Søren

解决方案

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 Uris 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.