Reputation: 2951
Each item of my SherlockListFragment
contains 3 TextView
s : a name and two numbers.
The data comes from the table objective
of my database, which has the following structure :
CREATE TABLE objective (
_id INTEGER PRIMARY KEY,
id_project INTEGER NOT NULL,
activity_code INTEGER NOT NULL,
day_duration INTEGER NOT NULL,
week_frequency INTEGER NOT NULL,
FOREIGN KEY(id_project) REFERENCES project(id_project)
);
Moreover, I have read that populating a list from a cursor should be done by using a loader (particularly when using a database because it can be a very slow operation).
I have found a SimpleCursorLoader
class here on stackoverflow, but it maps data to a field directly.
That is not really what I want, because as you can see, in my objective
table I have an activity_code
. So I would like to replace it by a string (I have an Enum that lists all of my activity codes and returns, for each one, a string resource identifier).
Do you know how I could manipulate data before it is displayed in the TextView
s ?
Here is my SherlockListFragment
public class ObjectivesDisplayFragment extends SherlockListFragment implements LoaderManager.LoaderCallbacks<Cursor>
{
private Activity activity;
private SimpleCursorAdapter adapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
return inflater.inflate(R.layout.objectives_display, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
activity = getActivity();
String[] columns = new String[] { "activity_code", "day_duration", "week_frequency" };
int[] to = new int[] { R.id.activityName, R.id.objectiveDuration, R.id.objectiveFrequency };
getLoaderManager().initLoader(0x01, null, this);
adapter = new SimpleCursorAdapter(activity.getApplicationContext(), R.layout.objective_row, null, columns, to, SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
setListAdapter(adapter);
}
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
return new SimpleCursorLoader(activity) {
@Override
public Cursor loadInBackground() {
DatabaseHelper dbHelper = DatabaseHelper.getInstance(activity);
String query = "SELECT _id, activity_code, day_duration, week_frequency FROM objective WHERE id_project = ?";
String[] args = new String[] { "1" }; // projectId
Cursor results = dbHelper.getReadableDatabase().rawQuery(query, args);
return results;
}
};
}
public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) {
adapter.swapCursor(cursor);
}
public void onLoaderReset(Loader<Cursor> arg0) {
adapter.swapCursor(null);
}
}
EDIT : I do not need to close the cursor and the database in SimpleCursorLoader > loadInBackground, right ? Otherwise the data could not be read. So is the closing operation automatically handled or do I need to do it myself elsewhere?
Upvotes: 4
Views: 1425
Reputation: 98
I guess this may work for you:
adapter.setViewBinder(new ViewBinder(){
@Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
String label = "Inactive";
if(columnIndex == 4) {
if(cursor.getInt(columnIndex) == 1) {
label = "Active";
}
TextView tv = (TextView) view.findViewById(R.id.status);
tv.setText(label);
return true;
}
return false;
}
});
setListAdapter(adapter);
Background information: I had a foreign key column (integer) in the table and wanted to resolve to it's string value (from linked table) upon populating in the list view. Column was at 4th index (5th column in set), so just used setViewBinder() to manipulate the required column.
Further my layout had 5 text views to display the 5 fields from cursor. One thing also NOTICEABLE here is, when using "if" conditions to catch your column indexes, make sure every conditional block must contain "return true". In such case where interpreter reaches "return false" - means your field didn't get manipulated.
I am sure the above code block is pretty much simple and easy to understand.
Upvotes: 3