Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the purpose of an Android projection map in a content provider?

I am looking at the Android notepad application sample code in <path_to_SDK>/samples/android-16/NotePad/src/com/example/android/notepad.

I was wondering if anyone could explain to me why the following code is needed in NotepadProvider.java?

// Creates a new projection map instance. The map returns a column name
// given a string. The two are usually equal.
sNotesProjectionMap = new HashMap<String, String>();

// Maps the string "_ID" to the column name "_ID"
sNotesProjectionMap.put(NotePad.Notes._ID, NotePad.Notes._ID);

// Maps "title" to "title"
sNotesProjectionMap.put(NotePad.Notes.COLUMN_NAME_TITLE,NotePad.Notes.COLUMN_NAME_TITLE);

// Maps "note" to "note"
sNotesProjectionMap.put(NotePad.Notes.COLUMN_NAME_NOTE, NotePad.Notes.COLUMN_NAME_NOTE);

// Maps "created" to "created"
sNotesProjectionMap.put(NotePad.Notes.COLUMN_NAME_CREATE_DATE, NotePad.Notes.COLUMN_NAME_CREATE_DATE);

// Maps "modified" to "modified"
sNotesProjectionMap.put(
        NotePad.Notes.COLUMN_NAME_MODIFICATION_DATE,
        NotePad.Notes.COLUMN_NAME_MODIFICATION_DATE)

I notice the projection map is used later in the query() method:

...
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(NotePad.Notes.TABLE_NAME);

/**
 * Choose the projection and adjust the "where" clause based on URI pattern-matching.
 */
switch (sUriMatcher.match(uri)) {
    // If the incoming URI is for notes, chooses the Notes projection
    case NOTES:
    qb.setProjectionMap(sNotesProjectionMap);
    break;
...

Why is this projection map needed?

like image 539
Umbungu Avatar asked Oct 05 '12 16:10

Umbungu


People also ask

What is the purpose of content provider in Android?

A content provider manages access to a central repository of data. A provider is part of an Android application, which often provides its own UI for working with the data. However, content providers are primarily intended to be used by other applications, which access the provider using a provider client object.

What are content providers how do you create your own content provider in Android?

A content provider manages access to a central repository of data. You implement a provider as one or more classes in an Android application, along with elements in the manifest file. One of your classes implements a subclass ContentProvider , which is the interface between your provider and other applications.

Which of the following is used to load data from content provider in Android?

Access Data from Content Provider To access a data from content provider, we need to use ContentResolver object in our application to communicate with the provider as a client. The ContentResolver object will communicate with the provider object ( ContentProvider ) which is implemented by an instance of class.


3 Answers

The Notepad application from the SDK demos is a sample application, one that should be an example of API use and good practices using those APIs, that is why they probably use a projection map. Although the Notepad sample doesn't really need a projection map the use of one is a good showcase for more complex cases when one is needed. For example, if I remember right, the Shelves application written by one of the Google engineers is using a projection map in its ContentProvider and that projection map isn't just a simple mapping with identical key-value pairs.

I've also added a link to the documentation of the method SQLiteQueryBuilder.setProjectionMap which has some details on why you would need a projection map.

like image 150
user Avatar answered Oct 20 '22 00:10

user


Its main purpose is to rename column names found in a cursor produced by a query.

@static declaration

SEARCH_PROJECTION_MAP = new HashMap<String, String>();
SEARCH_PROJECTION_MAP.put( OpenHelper.NAME, OpenHelper.NAME + " as _name" );
SEARCH_PROJECTION_MAP.put( OpenHelper.ID , OpenHelper.ID + " as _id" );  

@your query functionality

//if you query using sqliteQueryBuilder then
    sqLiteQueryBuilder.setProjectionMap( SEARCH_PROJECTION_MAP );

//example if you just query
    Cursor cursor = sqLiteQueryBuilder.query( db, projection, selection, selectionArgs, null, null, sortOrder );

the returned columns now are _name and _id in this example.

like image 34
Juan Mendez Avatar answered Oct 20 '22 01:10

Juan Mendez


Maybe someone needs more thorough explanation. I've gathered important facts about projection map:

  1. If you don’t need a projection map just don’t set it. This way projection names are processed “as is”, exactly as passed in via the projection array.

  2. Even the projection array is optional. If you pass null to the query, it generates a "SELECT *" operation. (actually that’s not recommended in SQL, because of the breakage that can occur if columns are added/removed, or re-ordered).

  3. Supplied projection map applies only to the selection list! So, you could map "store_name" => "bookstore.storename", and it would result in “select bookstore.storename ...”, but if you supplied "store_name" in the "order by" query builder parameter or one of the other qualified parameters, you can potentially end up with bad SQL.

  4. The projection map can be overruled. If the key part of a projection entry contains an "as" clause, the value part is ignored and the key part is inserted into the resulting SQL. For example "parrot as polly" => "cracker" will generate "SELECT parrot as polly ..." and no "cracker". The "as" can be either all upper-case or all lower-case (not mixed case) and must have at least one space before and after the word “as”.

Read more info in this article: http://www.mousetech.com/blog/android-projection-maps-explained/

like image 32
zkvarz Avatar answered Oct 20 '22 01:10

zkvarz