【问题标题】:UriMatcher won't correctly match all of my URIsUriMatcher 无法正确匹配我的所有 URI
【发布时间】:2014-08-11 23:14:14
【问题描述】:

很抱歉,还有另一个 UriMatcher 线程,但我无法理解为什么它不起作用。

我的 UriMatcher 有以下代码:

private static final int AGENDA = 200;
private static final int AGENDA_ID = 201;
private static final int AGENDA_AFTER = 202;
private static final int AGENDA_BEFORE = 203;
private static final int AGENDA_DATE_FILTERED = 204;

public static UriMatcher buildUriMatcher() {
    final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
    final String authority = AppContract.CONTENT_AUTHORITY;

    // Checks for a collection of items:
    // Ex: content://com.example.app/agenda
    matcher.addURI(authority, AppContract.PATH_AGENDA, AGENDA);
    // Checks for a single item
    // Ex: content://com.example.app/agenda/1
    matcher.addURI(authority, AppContract.PATH_AGENDA + "/#", AGENDA_ID);
    // Checks for a collection of items
    // Ex: content://com.example.app/agenda/after?date=2014-08-09%2014%3A17%3A51
    matcher.addURI(authority, AppContract.PATH_AGENDA + "/" + AppContract.AgendaEntry.AGENDA_AFTER + "/*", AGENDA_AFTER);
    // Checks for a collection of items
    // Ex: content://com.example.app/agenda/before?date=2014-08-09%2014%3A17%3A51
    matcher.addURI(authority, AppContract.PATH_AGENDA + "/" + AppContract.AgendaEntry.AGENDA_BEFORE + "/*", AGENDA_BEFORE);
    // Check for a collection of items
    // Ex: content://com.example.app/agenda?limit=before&date=2014-08-09%2014%3A35%3A47
    matcher.addURI(authority, AppContract.PATH_AGENDA + "/*/*", AGENDA_DATE_FILTERED);

    return matcher;
}

这是我的合同类:

public class AppContract {

    public static final String CONTENT_AUTHORITY = "com.example.app";

    public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);

    public static final String PATH_AGENDA = "agenda";


    /* Inner class that defines the table contents of the location table */
    public static final class AgendaEntry implements BaseColumns {

        public static final Uri CONTENT_URI =
                BASE_CONTENT_URI.buildUpon().appendPath(PATH_AGENDA).build();

        public static final String CONTENT_TYPE =
                "vnd.android.cursor.dir/" + CONTENT_AUTHORITY + "/" + PATH_AGENDA;
        public static final String CONTENT_ITEM_TYPE =
                "vnd.android.cursor.item/" + CONTENT_AUTHORITY + "/" + PATH_AGENDA;

        // Used in the Uri to select events
        public static final String AGENDA_BEFORE = "before";
        public static final String AGENDA_AFTER = "after";
        public static final String LIMIT = "limit";

        // Table name
        public static final String TABLE_NAME = "agenda";

        // Table columns
        public static final String COLUMN_APP_ID = "app_id";
        public static final String COLUMN_DATE = "date";
        public static final String COLUMN_TITLE = "title";
        public static final String COLUMN_SMALL_IMAGE_URL = "small_image_url";
        public static final String COLUMN_LARGE_IMAGE_URL = "large_image_url";
        public static final String COLUMN_HEADLINE = "headline";
        public static final String COLUMN_MESSAGE = "message";
        public static final String COLUMN_LAST_UPDATE = "last_update";

        public static Uri buildAgendaUri(long id) {
            return ContentUris.withAppendedId(CONTENT_URI, id);
        }

        public static Uri buildAgendaWithStartDate(String startDate) {
            return CONTENT_URI.buildUpon().appendPath(AGENDA_AFTER).appendQueryParameter(COLUMN_DATE, startDate).build();
        }

        public static Uri buildAgendaWithEndDate(String endDate) {
            return CONTENT_URI.buildUpon().appendPath(AGENDA_BEFORE).appendQueryParameter(COLUMN_DATE, endDate).build();
        }

        public static Uri buildAgendaWithDateLimit(String limit, String date) {
            return CONTENT_URI.buildUpon().appendQueryParameter(LIMIT, limit).appendQueryParameter(COLUMN_DATE, date).build();
        }

        public static String getLimitFromUri(Uri uri) {
            return uri.getQueryParameter(LIMIT);
        }

        public static String getDateFromUri(Uri uri) {
            return uri.getQueryParameter(COLUMN_DATE);
        }
    }
}

在 UriMatcher 的代码片段中,您可以看到由各自函数生成的每种 Uri 的示例。实际的 AGENDAAGENDA_ID Uris 匹配没有任何问题。但是,我无法让其他三个中的任何一个工作。 AGENDA_AFTERAGENDA_BEFORE总是得到-1AGENDA_DATE_FILTERED总是匹配到AGENDA

我在 Udacity 课程中的 Sunshine Android 应用程序上做了很多工作,其中他们有以下 Uris 之一,我的一个基于该 Uris:

content://com.example.android.sunshine.app/weather/94043?date=20140809
content://com.example.app                 /agenda /after?date=2014-08-09%2014%3A17%3A51

如下匹配:

matcher.addURI(authority, WeatherContract.PATH_WEATHER + "/*/*", WEATHER_WITH_LOCATION_AND_DATE);
matcher.addURI(authority, AppsssContract.PATH_AGENDA   + "/*/*", AGENDA_AFTER);

阳光一匹配没有任何问题,但我的根本没有。即使我更改了顺序并将其放在顶部,以防止任何其他 Uri 匹配(从 here 获得的信息),它仍然不起作用。

让我们以这个为例:

content://com.example.app/agenda/after?date=2014-08-09%2014%3A17%3A51
matcher.addURI(authority, AppContract.PATH_AGENDA + "/" + AppContract.AgendaEntry.AGENDA_AFTER + "/*", AGENDA_AFTER);

根据this 发布的每个段的 Uri 匹配器匹配。所以首先它应该匹配AppContract.PATH_AGENDA,即agenda。后面跟着一个/ 来分隔路径。在这之后我们得到AppContract.AgendaEntry.AGENDA_AFTER,它就是after。这也应该匹配。最后但同样重要的是,我们有一个/*,它应该与问号和日期查询匹配。但不知何故它无法匹配,我真的想知道我到底错过了什么。

我也想不通为什么这个匹配器应该匹配 Uri:

matcher.addURI(authority, AppContract.PATH_AGENDA, AGENDA);
content://com.example.app/agenda?limit=before&date=2014-08-09%2014%3A35%3A47

似乎? 似乎没有被正确地视为一个片段,尽管在上面的阳光示例中它似乎确实将其识别为一个片段。这是我能想到为什么它匹配这个 Uri 而不是 AGENDA_BEFOREAGENDA_AFTER 的 Uris 的唯一原因

我遇到了一堆类似的问题,例如this(由于我使用的变量不应该成为问题)或this(变量中没有/)或this导致我到this 问题,我仍然发现它的信息量最大。但我似乎仍然无法弄清楚。虽然我猜它会变得非常简单。

【问题讨论】:

    标签: android uri android-contentprovider


    【解决方案1】:

    您需要用“/”将您的查询与您的路径分开。

    不正确: content://com.example.app/agenda/after?date=2014-08-09%2014%3A17%3A51

    正确 content://com.example.app/agenda/after/date=2014-08-09%2014%3A17%3A51

    您也不应使用通配符 ( * ) 为您的查询创建匹配项

    不正确: matcher.addURI(authority, AppContract.PATH_AGENDA + "/" + AppContract.AgendaEntry.AGENDA_AFTER + "/*", AGENDA_AFTER);

    正确: matcher.addURI(authority, AppContract.PATH_AGENDA + "/" + AppContract.AgendaEntry.AGENDA_AFTER, AGENDA_AFTER);

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多