Cursor Adapters
Now that we've covered the basics of SQL, integrating SQLite databases into your apps, and Cursor behavior, we are finally ready to cover Cursor Adapters. Databases are a very important part to many popular apps, and knowing how to work with them is crucial. In addition to regular Cursor Adapters, we will explore Simple Cursor Adapters which make working with the results of databases even easier.
LEARNING OBJECTIVES
After this lesson, you will be able to:
- Define what the Cursor Adapter is doing
- Add a Cursor Adapter to link a database to the screen
- Define what the Simple Cursor Adapter is doing
- Add a Simple Cursor Adapter to link a database to the screen
Introduction: Cursor Adapters (15 mins)
We've already seen Adapters when working with ListViews, and how important they are for displaying your collections in your app. Similarly, Cursor Adapters exist for showing the data from the cursor in a ListView. All of the main concepts remain from Array Adapters, including custom views and notifying the adapter when data changes (a cursor in this case). Each time a new query is made, a new cursor is returned, and it can be swapped out in the adapter.
One important item to note is that your table in the database must have a column named _id that contains a unique id value for each entry.
Demo: Cursor Adapters (10 mins)
Now that we know what a cursor adapter does, let's create and implement a very basic one. We can start with the CursorAdapterDemo project, and make our adapter there.
//Get cursor
Cursor cursor = ExampleSQLiteOpenHelper.getInstance(MainActivity.this).getExampleList();
//Define CursorAdapter
CursorAdapter cursorAdapter = new CursorAdapter(MainActivity.this,cursor,0) {
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_1,parent,false);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
TextView textView = (TextView)view.findViewById(android.R.id.text1);
textView.setText(cursor.getString(cursor.getColumnIndex(ExampleSQLiteOpenHelper.COL_ITEM_NAME)));
}
};
//Set adapter
listView.setAdapter(cursorAdapter);
When creating the CursorAdapter, the constructor takes three parameters. The first is the current context, the second is the cursor that contains all of the data, and the final is for flags to customize the adapter. We aren't using any flags, so we can leave it at a default value of 0.
As you can see, there are two methods we are required to override. newView is simply responsible for inflating the list item layout. bindView is responsible for setting up all of the views in the layout, such as text and images.
Custom Cursor Adapters
Now that we've created a basic Cursor Adapter, let's try changing it to use a custom layout for the ListView item.
First, we need to create our new layout, then we can change our CursorAdapter.
//XML Layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/name_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/description_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
//Changed CursorAdapter
CursorAdapter cursorAdapter = new CursorAdapter(MainActivity.this,cursor,0) {
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.list_item_layout,parent,false);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
TextView nameTextView = (TextView)view.findViewById(R.id.name_text_view);
TextView descriptionTextView = (TextView)view.findViewById(R.id.description_text_view);
nameTextView.setText(cursor.getString(cursor.getColumnIndex(ExampleSQLiteOpenHelper.COL_ITEM_NAME)));
descriptionTextView.setText(cursor.getString(cursor.getColumnIndex(ExampleSQLiteOpenHelper.COL_ITEM_DESCRIPTION)));
}
};
There were only three changes we needed to make in order to use our custom layout:
1) Inflate the new layout 2) Get the new TextView 3) Set the new TextView to the description value