If you haven't yet,
Go to Part 1 of this two-part tutorial
In the previous post, we created a basic application that gives us a list showing the order in which the SW movies were released. We created a custom adapter that allowed us to insert object data into each row of the list using a custom row layout. What we still need to do, however, is find a way to save the data so that when we close the application and restart it, the data will persist.
As it stands now, however, we have no way to show that our application isn't actually saving the data because it gets automatically displayed each time we start it up. Just look at the onCreate method in ListFiller.java to see why; we need to add a feature that allows us to control when the movie list gets displayed. This is easily done with a button, so let's add one. Also, let's add an 'exit' button as well.
activity_list_filler.xml
<?xml
version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<Button
android:id="@+id/showList"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/showList"
android:onClick="onClick"/>
<Button
android:id="@+id/exit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/exit"
android:onClick="onClick"/>
</LinearLayout>
<ListView
android:id="@+id/theList"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="10sp" />
</LinearLayout>
|
Graphical Layout
So, above we have our new activity_list_filler.xml file and it's associated Graphical Layout. Now, let's add some code to ListFiller.java to get the buttons working.
ListFiller.java
import
java.util.ArrayList;
import
java.util.List;
import
android.os.Bundle;
import
android.app.Activity;
import
android.view.Menu;
import
android.view.View;
import
android.widget.ListView;
public
class ListFiller extends Activity {
ListView movieList;
@Override
protected void
onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_filler);
List
myList = new ArrayList();
movieList
= (ListView) findViewById(R.id.theList);
movieList.setAdapter(new
MovieListAdapter(this, R.layout.row_layout, myList));
}
public void onClick(View
view) {
@SuppressWarnings("unchecked")
ListView movieList = (ListView)
findViewById(R.id.theList);
MovieListAdapter swadapter =
(MovieListAdapter) movieList.getAdapter();
SWMovie swmovie = null;
switch (view.getId()) {
case R.id.showList:
List
myList = new ArrayList();
for
(int i = 1; i < 4; i++) {
String
g = Integer.toString(i);
int
k = i + 3;
String
j = Integer.toString(k);
myList.add(new
SWMovie("Movie " + g, "Episode " + k));
swmovie
= new SWMovie("Movie " + g, "Episode " + k);
swadapter.add(swmovie);
}
for
(int i = 1; i < 4; i++) {
String
g = Integer.toString(i);
int k = i
+ 3;
String
j = Integer.toString(k);
myList.add(new
SWMovie("Movie " + k, "Episode " + g));
swmovie
= new SWMovie("Movie " + k, "Episode " + g);
swadapter.add(swmovie);
}
break;
case R.id.exit:
finish();
break;
}
swadapter.notifyDataSetChanged();
}
@Override
public boolean
onCreateOptionsMenu(Menu menu) {
//
Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.list_filler,
menu);
return
true;
}
}
|
So, if you run the application now, you see the following screen upon start-up...
 |
Start-up screen |
Click "Show Movie List" and you see...
 |
Movie List screen |
Now, click "Exit Application" and restart the application once it closes. You should once again see the start-up screen with no list. This is because we haven't saved the list. We'll do that with SQLite now...
Actually, before we begin, if you'd like to learn more about SQLite now, check out the following links:
We need to create a class that creates the database, so let's do that and call it MovieSQLiteHelper and make it extend SQLiteOpenHelper.
MovieSQLiteHelper.java
import
android.content.Context;
import
android.database.sqlite.SQLiteDatabase;
import
android.database.sqlite.SQLiteOpenHelper;
import
android.util.Log;
public
class MovieSQLiteHelper extends SQLiteOpenHelper {
// name the Table
public static final String
TABLE_MOVIES = "movies";
// name the Columns of the
Table
public static final String
COLUMN_ID = "_id";
public static final String
COLUMN_MOVIE = "movie";
public static final String
COLUMN_EPISODE = "episode";
private static final String
DATABASE_NAME = "movies.db";
private static final int
DATABASE_VERSION = 1;
// Database creation
declaration
private static final String
DATABASE_CREATE = "create table "
+ TABLE_MOVIES + "(" +
COLUMN_ID
+ " integer primary key
autoincrement, " + COLUMN_MOVIE
+ " text not null, " +
COLUMN_EPISODE + " text not null" + ")";
// our object constructor
public
MovieSQLiteHelper(Context context) {
super(context,
DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void
onCreate(SQLiteDatabase db) {
db.execSQL(DATABASE_CREATE);
}
@Override
public void
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(MovieSQLiteHelper.class.getName(),
"Upgrading database from version
" + oldVersion + " to "
+ newVersion + ", which will
destroy all old data");
db.execSQL("DROP TABLE IF EXISTS
" + TABLE_MOVIES);
onCreate(db);
}
}
|
Again, if the above looks totally alien to you, or if you're having a hard time following the code, I encourage you to check out the links above.
Now, we're going to create a class which acts as a Data Access Object (DAO). The DAO is a database handler that manages the data and converts objects contained within the database into Java Objects. We'll call the class MoviesDataSource...
MoviesDataSource.java
import
java.util.ArrayList;
import
java.util.List;
import
android.content.ContentValues;
import
android.content.Context;
import
android.database.Cursor;
import
android.database.SQLException;
import
android.database.sqlite.SQLiteDatabase;
public
class MoviesDataSource {
private SQLiteDatabase
database;
private MovieSQLiteHelper
dbHelper;
private String[] allColumns
= { MovieSQLiteHelper.COLUMN_ID,
MovieSQLiteHelper.COLUMN_MOVIE, MovieSQLiteHelper.COLUMN_EPISODE };
public
MoviesDataSource(Context context) {
dbHelper = new
MovieSQLiteHelper(context);
}
public void open() throws SQLException {
database = dbHelper.getWritableDatabase();
}
public void close() {
dbHelper.close();
}
public SWMovie createSWMovie(String movie,
String episode) {
ContentValues values = new
ContentValues();
values.put(MovieSQLiteHelper.COLUMN_MOVIE, movie);
values.put(MovieSQLiteHelper.COLUMN_EPISODE,
episode);
long insertId =
database.insert(MovieSQLiteHelper.TABLE_MOVIES, null, values);
Cursor cursor =
database.query(MovieSQLiteHelper.TABLE_MOVIES,
allColumns,
MovieSQLiteHelper.COLUMN_ID + " = " + insertId, null,
null, null, null);
cursor.moveToFirst();
SWMovie newSWMovie =
cursorToSWMovie(cursor);
cursor.close();
return newSWMovie;
}
public void deleteSWMovie(SWMovie swmovie) {
long id = swmovie.getId();
System.out.println("SWMovie deleted
with id: " + id);
database.delete(MovieSQLiteHelper.TABLE_MOVIES, MovieSQLiteHelper.COLUMN_ID
+ " = " + id, null);
}
public List<SWMovie> getAllSWMovie() {
List<SWMovie> swmovies = new
ArrayList<SWMovie>();
Cursor cursor =
database.query(MovieSQLiteHelper.TABLE_MOVIES,
allColumns, null, null, null,
null, null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
SWMovie swmovie =
cursorToSWMovie(cursor);
swmovies.add(swmovie);
cursor.moveToNext();
}
cursor.close();
return swmovies;
}
private SWMovie cursorToSWMovie(Cursor
cursor) {
SWMovie swmovie = new SWMovie();
swmovie.setId(cursor.getLong(0));
swmovie.setMovie(cursor.getString(1));
swmovie.setEpisode(cursor.getString(2));
return swmovie;
}
}
|
I threw in some code so that movies can be deleted from the list, but I'll leave it as an extra exercise for you to work a 'delete movie' button into the application.
Now, we need to update the main activity to make sure the data gets saved...
ListFiller.java
import
java.util.ArrayList;
import
java.util.List;
import
android.os.Bundle;
import
android.app.Activity;
import
android.view.Menu;
import
android.view.View;
import
android.widget.ListView;
public
class ListFiller extends Activity {
ListView movieList;
private MoviesDataSource
datasource;
@Override
protected void
onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_filler);
datasource
= new MoviesDataSource(this);
datasource.open();
List
myList = datasource.getAllSWMovie();
movieList
= (ListView) findViewById(R.id.theList);
movieList.setAdapter(new
MovieListAdapter(this, R.layout.row_layout, myList));
}
public void onClick(View
view) {
@SuppressWarnings("unchecked")
ListView movieList = (ListView)
findViewById(R.id.theList);
MovieListAdapter swadapter =
(MovieListAdapter) movieList.getAdapter();
SWMovie swmovie = null;
switch (view.getId()) {
case R.id.showList:
List
myList = new ArrayList();
for
(int i = 1; i < 4; i++) {
String
g = Integer.toString(i);
int
k = i + 3;
String
j = Integer.toString(k);
myList.add(new
SWMovie("Movie " + g, "Episode " + k));
swmovie
= new SWMovie("Movie " + g, "Episode " + k);
swmovie
= datasource.createSWMovie(swmovie.getMovie(),
swmovie.getEpisode());
swadapter.add(swmovie);
}
for
(int i = 1; i < 4; i++) {
String
g = Integer.toString(i);
int
k = i + 3;
String
j = Integer.toString(k);
myList.add(new
SWMovie("Movie " + k, "Episode " + g));
swmovie
= new SWMovie("Movie " + k, "Episode " + g);
swmovie
= datasource.createSWMovie(swmovie.getMovie(),
swmovie.getEpisode());
swadapter.add(swmovie);
}
break;
case R.id.exit:
finish();
break;
}
swadapter.notifyDataSetChanged();
}
@Override
protected void onResume() {
datasource.open();
super.onResume();
}
@Override
protected void onPause() {
datasource.close();
super.onPause();
}
@Override
public boolean
onCreateOptionsMenu(Menu menu) {
//
Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.list_filler,
menu);
return
true;
}
}
|
Make sure to read through all the code in ListFiller.java and understand how the database is made to store and display the data. Run the application, click "Show Movie List", click "Exit Application" after the list is displayed, and once the application is closed, restart the application. The movie list should display upon opening, which means the data has been correctly stored in the database.
If you have any questions or concerns about this tutorial, please drop a comment below. Thanks for following!