How to implement complex queries using a Content Provider?

前端 未结 3 806
独厮守ぢ
独厮守ぢ 2021-02-05 23:11

I am asking this because I am not quite sure of how to work with Android Content Providers. I have a subset of my database with 8 tables and I need to create complex queries to

相关标签:
3条回答
  • 2021-02-05 23:46

    Below code worked for me. Inside your Application's Content Provider:

    public static final String PATH_JOIN_TWO_TABLES = "my_path";
    
        public static final Uri URI_JOIN_TWO_TABLES =
                Uri.parse("content://" + AUTHORITY + "/" + PATH_JOIN_TWO_TABLES);
    
        private static final int ID_JOIN_TWO_TABLES = 1001;
    
        private static final UriMatcher sURIMatcher = new UriMatcher(
                UriMatcher.NO_MATCH);
    
        static {
            sURIMatcher.addURI(AUTHORITY,
                    PATH_JOIN_TWO_TABLES + "/#", ID_JOIN_TWO_TABLES );
        }
    
        @Nullable
        @Override
        public Cursor query(@NonNull Uri uri, String[] projection, String selection,String[] selectionArgs,
                            String sortOrder, CancellationSignal cancellationSignal) {
    
            int uriType = sURIMatcher.match(uri);
                switch (uriType) {
    
                    case ID_JOIN_TWO_TABLES:
                        return getWritableDatabase()
                                .rawQuery("select * from " +
                                        "table_one" + " LEFT OUTER JOIN "
                                        + "table_two" + " ON ("
                                        + "table_one.ID"
                                        + " = " + "table_two.id" + ")", null);
                }
            return super.query(uri, projection, selection, selectionArgs, sortOrder, cancellationSignal);
        }
    

    And while making the Query inside your Activity or Fragment:

     Cursor cursor = getActivity().getContentResolver()
                    .query(ContentUris.withAppendedId(MYContentProvider.URI_JOIN_TWO_TABLES, MyContentProvider.ID_JOIN_TWO_TABLES), null, null, null, null);
    

    Hope it works for you.

    0 讨论(0)
  • 2021-02-05 23:47

    For simple queries use selectionArgs in ContentProvider. It works like below

    String[] args = { "first string", "second@string.com" };
    Cursor cursor = db.query("TABLE_NAME", null, "name=? AND email=?", args, null);
    

    Having the TABLE_ID inside the to create a different queries for each table.

    Refer following class for all multiple table in content providers

    1. Vogella Tutorial 1
    2. Vogella Tutorial 2
    3. Best practices for exposing multiple tables using content providers in Android
    0 讨论(0)
  • 2021-02-05 23:57

    I actually found the answer to my question in the most obvious place: the android documentation.

    First Question: Implement a rawQuery. Did it like this:

    Inside of my switch-case in the content provider I added a new URI, which for me is a JOIN between to tables, so I created a new ContentUri constant for it, a new ID, and registered it on the UriMatcher and then wrote the rawQuery. So MyProvider now looks a litte bit like this:

    public class MyProvider extends ContentProvider {
    ...
    // JOIN paths
        private static final String PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = 
                "relationship_join_person_get_relatives";
    ...
    public static final Uri CONTENT_URI_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = Uri
                .parse("content://" + AUTHORITY + "/"
                        + PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES);
    ...
        private static final int RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = 21;
    private static final UriMatcher sURIMatcher = new UriMatcher(
                UriMatcher.NO_MATCH);
        static {
    ...
    //JOINS
            sURIMatcher.addURI(AUTHORITY, PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES + "/#",
                    RELATIONSHIP_JOIN_PERSON_GET_RELATIVES);
    ...
    
    public Cursor query(Uri uri, String[] projection, String selection,
                String[] selectionArgs, String sortOrder) {
    
            // Uisng SQLiteQueryBuilder instead of query() method
            SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
    
            // check if the caller has requested a column which does not exists
            //checkColumns(projection);
    
            int uriType = sURIMatcher.match(uri);
    
            switch (uriType) {
            ...
            case RELATIONSHIP_JOIN_PERSON_GET_RELATIVES:
                db = dbHelper.getWritableDatabase();
                String[] args = {String.valueOf(uri.getLastPathSegment())};
                Cursor cursor = db.rawQuery(
                        "SELECT p1.first_name, p1.last_name " +
                        "FROM Person p1, Person p2, Relationship r " +
                        "WHERE p1.id = r.relative_id AND " +
                        "p2.id = r.related_id AND " + 
                        "p2.id = ?", args);
                cursor.setNotificationUri(getContext().getContentResolver(), uri);
                return cursor;
            ...
    }
    

    And to call the query() method and pass the id ad a parameter I did this in my controller:

    String[] projection = { PersonModel.C_FIRST_NAME,
                    PersonModel.C_LAST_NAME };
            Cursor cursor = context.getContentResolver().query(
                    ContentUris.withAppendedId(
                            AkdemiaProvider.CONTENT_URI_RELATIONSHIP_JOIN_PERSON_GET_RELATED, id), 
                            projection, null, null, null);
    

    Second question: Having the TABLE_ID constant is useful to have a query for each table passing an id as a parameter, I didn't know how to call the query method passing such id and this is how the Android Developer Documentation explains how to do so using ContentUris.withAppendedId

    // Request a specific record.
    
    
    Cursor managedCursor = managedQuery(
                    ContentUris.withAppendedId(Contacts.People.CONTENT_URI, 2),
                    projection,    // Which columns to return.
                    null,          // WHERE clause.
                    null,          // WHERE clause value substitution
                    People.NAME + " ASC");   // Sort order.
    

    I you guys want to see the whole documentation go to this link.

    Hope this helps to anyone else having the same problem to understand ContentProvider, ContentUris and all that :)

    0 讨论(0)
提交回复
热议问题