Note that there are some explanatory texts on larger screens.

plurals
  1. POContentProvider with multiple tables
    text
    copied!<p>I want to implement a <code>ContentProvider</code> that manipulates multiple tables. Here is what I tried so far. I wrote a Java <code>Interface</code> that represents the CRUD operations that every table should implement in its CRUD class. </p> <pre><code>public interface CRUDHandler { //UPDATE int update(Uri uri, ContentValues values, String selection,String[] selectionArgs); //READ Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) ; //CREATE Uri insert(Uri uri, ContentValues values); //DELETE int delete(Uri uri, String selection, String[] selectionArgs); //get Mime type String getType(Uri uri); } </code></pre> <p>Then I wrote an <code>abstract</code> <code>class</code> that defines a static <code>UriMatcher</code> for the <code>ContentProvider</code> so each class that <code>extends</code> this class should add its <code>Uri</code> that identifies it and provide an implementation for each method in interface.</p> <p>The class looks like this:</p> <pre><code>public abstract class ApplicationCRUD implements CRUDHandler{ public static final UriMatcher sUriMatcher; static { sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); } } </code></pre> <p>Further, I created a class for each table that <code>extends</code> this class and adds its <code>Uri</code>'s to the <code>UriMatcher</code> from the abstract class.</p> <p>Here is an example:</p> <pre><code>public class Table1CRUD extends ApplicationCRUD { //Setup Projection Map for Table1 private static HashMap&lt;String , String&gt;sTable1ProjectionMap; static { sTable1ProjectionMap.put(ApplicationProviderMetaData.Table1MetaData._ID, ApplicationProviderMetaData.Table1MetaData.TABLE_NAME+"."+ApplicationProviderMetaData.Table1MetaData._ID); sTable1ProjectionMap.put(ApplicationProviderMetaData.Table1MetaData.COL1, ApplicationProviderMetaData.Table1MetaData.TABLE_NAME+"."+ApplicationProviderMetaData.Table1MetaData.COL1); sTable1ProjectionMap.put(ApplicationProviderMetaData.Table1MetaData.COL2, ApplicationProviderMetaData.Table1MetaData.TABLE_NAME+"."+ApplicationProviderMetaData.Table1MetaData.COL2); } public static final int INCOMING_SINGLE_URI_INDICATOR = 5; public static final int INCOMING_COLLECTION_URI_INIDICATOR = 6; static { //standard URI sUriMatcher.addURI(ApplicationProviderMetaData.AUTHORITY, "t1", INCOMING_COLLECTION_URI_INIDICATOR); sUriMatcher.addURI(ApplicationProviderMetaData.AUTHORITY, "t1/#", INCOMING_SINGLE_URI_INDICATOR); //here add your custom URI } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { // TODO Auto-generated method stub return 0; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // TODO Auto-generated method stub return null; } @Override public Uri insert(Uri uri, ContentValues values) { // TODO Auto-generated method stub return null; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // TODO Auto-generated method stub return 0; } @Override public String getType(Uri uri) { // TODO Auto-generated method stub return null; } } </code></pre> <p>Now my <code>ContentProvider</code> looks like this: </p> <pre><code>public class ApplicationProvider extends ContentProvider{ //Define TAG FOR EACH CLASS FOR DEBUGGING private static final String TAG = "ApplicationProvider"; // Application CRUD Handlers use to support multiple tables inside the content provider private static Table1CRUD table1CRUD; private static Table2CRUD table2CRUD; static { table1CRUD = new Table1CRUD(); table2CRUD= new Table2CRUD(); } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { int uriMatchResult = ApplicationCRUD.sUriMatcher.match(uri); //case Table1 if(uriMatchResult == Table1CRUD.INCOMING_COLLECTION_URI_INIDICATOR ||uriMatchResult == Table1CRUD.INCOMING_SINGLE_URI_INDICATOR ) { return table1CRUD.delete(uri, selection, selectionArgs); } case Table2 else if(uriMatchResult == Table2.INCOMING_COLLECTION_URI_INDICATOR|| uriMatchResult ==Table2.INCOMING_SINGLE_URI_INDICATOR){ return table2CRUD.delete(uri, selection, selectionArgs); } else{ throw new IllegalArgumentException("Unknown Uri "+uri); } } </code></pre> <p>Now I am using the <code>SQLiteOpenHelper</code> as a private class in the <code>ContentProvider</code> and I define an instance of it in my <code>ContentProvider</code>. Should I modify the interface and supply each CRUD method that object <code>Dependency Injection</code> to let each function use it to access the database? I also want to know what you think about this approach: Is it good enough? Does it make the thing I am trying to do efficiently? What modification can I do to improve this design?</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload