Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Database Access Design Approach

Tags:

android

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 -

  1. How can I (if its even possible) manage the cursors life cycle from outside an Activity?
  2. Should each activity even be creating an instance of this data handler class and passing an instance of Context to it? Perhaps my design approach is wrong and I should expose these data access functions as static methods that take an instance of the calling activity as a parameter. That way I could perform managed queries and let the activity take care of managing the cursors life cycle?

I'd really like to get an understanding of the best approach. Any advice would be greatly appreciated

like image 551
Brian Avatar asked Nov 05 '22 09:11

Brian


1 Answers

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 :)

like image 141
Juri Avatar answered Nov 11 '22 11:11

Juri