Ready to watch this entire course?
Become a member and get unlimited access to the entire skills library of over 4,900 courses, including more Developer and personalized recommendations.Start Your Free Trial Now
- View Offline
- Exploring local data storage options
- Creating an Android virtual device
- Starting a new project
- Defining preferences with Java and activities
- Creating and reading JSON and XML data files
- Creating a new SQLite database
- Inserting and retrieving data in the database
Skill Level Intermediate
Once you've created your Database Open Helper class, the next step in following the best practices for managing SQLite is to create another class called a data source. Its methods, the data sources methods, will be called by the rest of the app. You can create multiple data sources in an application. For example, you might create one data source for each table in a database or one data source for each set of tasks. How you architect that is up to you. In my example, I only have a single table right now, so I'll use a single data source class.
I'm working in a version of the project named data source that already has a Database Open Helper class named ToursDBOpenHelper, and right now its methods are being called directly by the main activity. I'll create a new data source class, and I'll put it in the same package as the Open Helper. I'll right-click on the .db package and I'll create the new Java class and I'll name this ToursDataSource. Data source classes don't extend any particular Superclass.
In fact, my data source class won't have an explicit Superclass at all. I'll click Finish and that creates the class structure. The first step in creating the data source class is to create a public constructor method. I'll move the cursor inside the class declaration, and I'll type in public, then the name of the class, and the constructor method will receive a single argument, the context of the current activity. I'll type the name of the context class and press Ctrl+Space and import it, and I'll name the argument context.
So, that's the only constructor method that the data source class will have. In order to instantiate this class, the activity must pass in the context. Next, I'll declare the instances of the Database Open Helper and the Database. Right now, I've done this in the MainActivity class, so I'll go steal that code from the activity and bring it into the data source. I'll go to the MainActivity class. I'll expand this to full screen to make it a little bit easier to read, and here are two declarations I need, one for the Open Helper and one for the Database.
I'll copy those to the clipboard. I'll come back to the data source class and I'll paste them inside the class declaration but outside of any methods, and Eclipse automatically adds the required imports. I'll instantiate the Database Open Helper class when the data source is instantiated. So I'll add code to the ToursDataSource constructor method. Once again, I have a code that will do this. I'll go back to the MainActivity and scroll down toward the bottom of the onCreate method.
I'll take these two lines of code that are instantiating the Open Helper and the Database. I'll copy those to the clipboard. I'll come back to the data source and then I'll place the cursor inside the constructor method and paste that code into place. I need to make one change. When I instantiated the Open Helper from the activity, I passed in this as the context. This refers to the data source, not the activity, but I'm receiving the activity context right here.
So I'll just take that context argument and pass it into the Open Helper's constructor. In a way, that's all I really need to do, but I'm going to make this code even easier to use by adding another couple of methods called open and close. They'll be public methods, and the idea will be that any activity in my application can open or close the database connection anytime it wants to. So I'll create two new methods. First, I'll create a method called open. It will return void, and then I'll take that bit of code and duplicate it.
For the second version, I'll name it close. Whenever each of these methods are called, I'm going to want to log them in the LogCat console. So I'm going to set up a constant that I can use as my LogCat tag. Once again, I'll get that from the MainActivity class. I'll go to the MainActivity to the top of the class, and I'll copy the Log tag constant. Then I'll come back to the DataSource and paste it into place. Then I'll go to the open method.
I'll type in the name of the Log class, and I'll add an import, then I'll call the .i method for info. I'll pass in the LOGTAG argument and then a message of Database opened and then I'll repeat that for the close method. I'll duplicate that line of code, move it into place, and change the message to Database closed. I'll add code to actually open and close the database. The code I need to open the database is already here.
It's actually in the constructor method. When you call the getWritableDatabase method that opens the database connection. So I'm just going to take this line of code and move it into the open method. I'll hold down my Option key on Mac or the Alt key on Windows and then press the down arrow and move the code into place. Then for the close method, I'll call the Open Helper's close method. So now I have all the pieces I need for a basic data source class.
I have a constructor method that instantiates my Open Helper, and I have code to open and close the database connection. Now I'll modify my MainActivity. The MainActivity is no longer going to deal directly with the database open helper or the database. That will all be hidden inside the data source object. So I'll delete these two declarations, and I'll replace them with the declaration of an instance of ToursDataSource, my new data source class.
I'll name it datasource and I won't instantiate it yet. I'll wait 'til I get to the onCreate method. Now I'll go down to the onCreate method, and once again, I'll get rid of the code that's dealing directly with the database Open Helper and the Database, and I'll replace it with instantiating the data source. I'll pass in this as the context. Finally, if you want to maintain a persistent database connection for the entire lifetime of the activity, you can add code to the methods onPause and onResume.
These are methods that are automatically called by Android during the life cycle of the activity. As the activity comes to the screen, it's onResume method is called. So I'll go down to the bottom of the activity code, I'll place the cursor after any of the existing methods, I'll type in onResume, I'll press Ctrl+Space, and choose the onResume method. I'll get rid of the comment and then after the call to the Superclass' OnResume method, I'll call datasource.open.
Similarly, you should explicitly close the data source connection whenever the activity pauses. The onPause method is called as the activity closes down. So I'll type in onPause. I'll press Control+Space. I'll choose the onPause method that creates the override. After the call to the Superclass method, I'll call datasource.close. Now we're ready to test the whole thing. Remember, my data source is outputting to the LogCat console whenever its open and close methods are called.
So I'll easily be able to track when these operations are happening. I'll go to my LogCat console, and you can clear any existing output by clicking on the Clear Log button, then I'll run the application in the emulator. As the application comes to the screen, the onPause method is called automatically as a part of the activity life cycle. And I see the message database open. I'll leave the activity by clicking the Back button.
I'm going to move the emulator out of the way so we can see these messages. And I see the message database closed. I'll go to my application list, and I'll reopen the application, and once again, the activity opens and the database opens. I'll click the Back button and the database closes. Every activity in your application can open and close the database connection as needed. It's also useful to know that you can add as many calls to the open method as you want to.
The connection object within any activity is cached. So you don't have to worry about calling the open method too many times, but you should make sure that you're explicitly closing the connection whenever the activity is going away. That will eliminate the possibility of what are known as database connection leaks. A database connection leak can cause memory and performance issues. So by adding the code to explicitly open and close the database when needed, will make your application work well, work fast, and give you a reliable way to work with structured data.