Writing ContentProvider Wrapper Methods
Hey everyone,
Forgot that I never got around to writing this post. Basically this example/code snippet will be a lesson on writing convenience methods that work off of the custom content providers that we created in https://thinkandroid.wordpress.com/2010/01/13/writing-your-own-contentprovider/.
So, working off of the NotesContentProvider from earlier, let’s write some nice wrapper methods! This example will primarily teach you how you can intelligently interact with your content provider / SQLite3 database.
public class NotesDB { /** * */ private NotesDB () { } private static final NotesDB instance = new NotesDB (); public static NotesDB getInstance() { return instance; } // adds a new note with a given title and text public void addNewNote(ContentResolver contentResolver, String title, String text) { ContentValues contentValue = new ContentValues(); // note that we don't have to add an id as our table set id as autoincrement contentValue.put(Notes.TITLE, title); contentValue.put(Notes.TEXT, text); contentResolver.insert(Notes.CONTENT_URI, contentValue); } // checks to see if a note with a given title is in our database public boolean isNoteInDB(ContentResolver contentResolver, String title) { boolean ret = false; Cursor cursor = contentResolver.query(Notes.CONTENT_URI, null, Notes.TITLE + "='" + title + "'", null, null); if (null != cursor && cursor.moveToNext()) { ret = true; } cursor.close(); return ret; } // get the note text from the title of the note public long getTextFromTitle(ContentResolver contentResolver, String title) { String ret = ""; String[] projection = new String[] { Notes.TEXT }; Cursor cursor = contentResolver.query(Notes.CONTENT_URI, projection, Notes.TITLE + "='" + title + "'", null, null); if (null != cursor && cursor.moveToNext()) { int index = cursor.getColumnIndex(Notes.TEXT); ret = cursor.getString(index); } cursor.close(); return ret; } public void updateTextFromTitle(ContentResolver contentResolver, String title, String text) { ContentValues contentValue = new ContentValues(); contentValue.put(Notes.TEXT, text); contentResolver.update(Notes.CONTENT_URI, contentValue, Notes.TITLE + "='" + title + "'", null); } // erases all entries in the database public void refreshCache(ContentResolver contentResolver) { int delete = contentResolver.delete(Notes.CONTENT_URI, null, null); System.out.println("DELETED " + delete + " RECORDS FROM CONTACTS DB"); } }
And so here we have an example of a wrapper method that adds a new note, that checks the existence of a note, that retrieves information of a note, that updates a note in the database, and that deletes an entry (in this case all entries) from our database.
I hope this gives you a better idea of how to interact with your content provider effectively. These wrapper functions are nice as you never need to worry about finalizing Cursor exceptions (often times, if you open a cursor in a class and that class finishes before you close the cursor, either an SQLite warning or exception will get thrown telling you there was a cursor finalizing exception) since each method opens and closes the cursor for you.
And ultimately, this is just an example of good object oriented programming! No one wants to see all this messy code communicating with content providers in the Activities themselves … so why not right a pretty wrapper function around it all?
Hope this was helpful and a good way to end the Content Provider tutorials. Let me know if you have questions.
Happy coding.
– jwei
This seems to be a nice way to separate the responsibility.
Implementing this way other classes does not need to worry about any issues related to database as in no manner they have to interact with the cursor.
But i was wondering if i want to adapt to this pattern fully how can i substitute use of CursorAdapter, that too without failing to loose the notification functionality.
Thanks a lot. Very helpful indeed.
hi
Im creating a new notesDB
by doing like this
notesDB = NotesDB.getInstance();
Why cant i create it like this
NotesDB noDB = new NotesDB();
What is the reason for doing it like this “getInstance()” , purely object orienter ??
Hey ERik,
It’s recommended that for these database objects they exist once and only once in memory as Singletons (http://en.wikipedia.org/wiki/Singleton_pattern).
– jwei
I noticed that this is a singleton implementation, hence the question:
if the app uses a service in a separate process (for networking and storing data using the content provider) and an activity uses the content provider (for showing data to screen), will this singleton implementation follow good design, or will it crash and burn ?
Looks like getTextFromTitle should return a String, not a long. Thanks for the guides, they’re very helpful!
Hey jwei,
Thanks a lot your code so helpful to me.