I have a general Android design question around data access. I have a number of activities in my application that need to access a SQLite database. In order to wrap up all data access logic in one place I have created a DatbaseHandler class that takes care of all data access logic. This class takes care of building up where clauses, calling the database and interrogating the resulting cursor to retrieve the query results and return them to the caller. The purpose of this class is to wrap all data access code in one place so that it can be easily managed and maintained as opposed to having data access logic scattered across all activities. Each activity that needs access to the database creates an instance of this DatabaseHandler class and passes it a reference of android.content.Context. The DatabaseHandler class then uses this Context object to call an underlying content provider as follows context_i.getContentResolver().query(...).
My data access logic (cursor handling logic to be specific) is not in the activity and so I cannot manage the cursors life cycle, therefore there is likely to be memory leaks.
My questions are as follows -
I'd really like to get an understanding of the best approach. Any advice would be greatly appreciated
The standard approach:
Normally if you have a ContentProvider written by yourself and you registered it correctly in your manifest.xml file, you can just do (for instance)
@Override
public void onCreate(Bundle savedInstanceState){
...
if (getIntent().getData() == null) {
getIntent().setData(MyMetaData.CONTENT_URI);
}
Cursor cursor = managedQuery(getIntent().getData(), null, null, null, null);
//create an appropriate adapter and bind it to the UI
...
}
this will automatically call the ContentProvider that is able to handle the given content uri, given you registered it in the manifest.xml file like
<provider android:name="MyContentProvider" android:authorities="com.mycompany.contentprovider.MyContentProvider" />
I always suggest people to take a look at the Notepad example for learning how ContentProviders should be implemented.
Alternatives:
Generally speaking, if you need to access your data just within your activities I would stick to the "Standard approach" using ContentProviders, which btw. probably makes it the most flexible solution.
If your solution needs to access the data also from non-Activity classes where you don't have the "managedQuery" metods, then you could implement some kind of DAO (Data Access Object) classes yourself. An example could be
public class MyDataDao implements IMyDataDao {
private ContentResolver contentResolver;
public MyDataDao(ContentResolver contentResolver){
this.contentResolver = contentResolver;
}
@Override
public MyDataObject readMyDataObjectById(long id){
MyDataObject result = null;
Cursor myDataObjectCursor = contentResolver.query(...);
if(myDataObjectCursor != null && myDataObjectCursor.moveToFirst()){
result = new MyDataObject();
result.setTitle(myDataObjectCursor.get..);
...
}
myDataObjectCursor.close();
return result;
}
}
That may work as well. You then call your DAO
IMyDataDao dao = new MyDataDao(context.getContentResolver());
MyDataObject anObj = dao.readMyDataObjectById(10);
...
Hope that pointed you in the right direction :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With