How can I merge two SimpleCursorAdapters in Android? - android

I am using two SimpleCursorAdapters to display text and images in a row in my Listview. The problem is that when calling these Adapters two times they conflict with each other. In the end my Listview only shows the data of the SimpleCursorAdapter that I called last.
What I need to do is merge those two SimpleCursorAdapters although they use different sql databases.
Any ideas to solve this??
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.reminder_list);
mDbHelper = new RemindersDbAdapter(this);
mImageHelper = new ImageAdapter(this);
mDbHelper.open();
mImageHelper.open();
fillData();
fillImages();
registerForContextMenu(getListView());
}
//
// Fills the ListView with the data from the SQLite Database.
//
private void fillData() {
Cursor remindersCursor = mDbHelper.fetchAllReminders();
startManagingCursor(remindersCursor);
// Creates an array with the task title.
String[] from = new String[] {RemindersDbAdapter.KEY_TITLE, RemindersDbAdapter.KEY_BODY};
// Creates an array for the text.
int[] to = new int[] {R.id.text1, R.id.text2};
// SimpleCursorAdapter which is displayed.
SimpleCursorAdapter reminders = new SimpleCursorAdapter(this, R.layout.reminder_row, remindersCursor, from, to);
setListAdapter(reminders);
}
//
// Fills the ListView with the images from the SQLite Database.
//
private void fillImages() {
Cursor imageCursor = mImageHelper.fetchAllImages();
startManagingCursor(imageCursor);
// Creates an array with the image path.
String[] fromImage = new String[] {ImageAdapter.KEY_IMAGE};
// Creates an array for the text.
int[] toImage = new int[] {R.id.icon};
// SimpleCursorAdapter which is displayed.
SimpleCursorAdapter images = new SimpleCursorAdapter(this, R.layout.reminder_row, imageCursor, fromImage, toImage);
setListAdapter(images);
}

You can use the MergeCursor class to expose a number of individual cursors as a single cursor. As your adapters bind different columns->widgets, you may have to write your own subclass of SimpleCursorAdapter (or just CursorAdapter) so that you can do the correct type of binding depending on the row.

how about creating your own adapter (extend BaseAdapter) , which will point to the correct data each time it needs to ?
this way you can have full control over when and where to show each item.
you can even use the 2 adapters and use them for the new adapter.

What I need to do is merge those two SimpleCursorAdapters although they use different sql databases.
If the two adapters are truly different (e.g., different row layouts), use my MergeAdapter to combine your two existing adapters into one, then use the MergeAdapter with your ListView.
However, in your case, it would appear that you simply have two Cursors with different contents, in which case superfell's answer of using MergeCursor is probably a better approach.

Related

How to use an ArrayAdapter to return and show a ListView

I am writing code for an mp3 player I am trying to create. I am only at the start of the project and want to be able to read and show all of the mp3 files that is on my sd card. I don't want to use the direct path method. Now this code I have written gathers all of the mp3 files for me but the only problem is that it does not view them on screen for me. The app shows a blank screen, but doesn't crash.
I got help and advice off of a tutor and I was told to use an ArrayAdapter to view the results but I can't find any help to show it. If anyone could please help that would be great.
Here is my code in the onCreate method;
ListView list;
Cursor cursor;
int columnIndex;
int count;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//list = (ListView) findViewById(R.id.list);
//A array is created that display the 3 fields
String[] displayMusic = {MediaStore.Audio.Media._ID, MediaStore.Audio.Media.DISPLAY_NAME, MediaStore.Audio.Media.TITLE};
//the cursor displays all of the audio in the sd card, just to limit to .mp3 files now
cursor = getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, displayMusic, null, null, null);
//this is the loop that gather all of the .mp3 files
int pos = 1;
ArrayList<String> listOfMp3s = new ArrayList<String>();
while (cursor.moveToNext())
{
if(cursor.getString(pos).endsWith("mp3"))
{
listOfMp3s.add(cursor.getString(pos));
}
}
String[] displayFields = new String[] {MediaStore.Audio.Media.DISPLAY_NAME};
int[] displayViews = new int[] {android.R.id.text1};
//setListAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, cursor, displayFields, displayViews);
ArrayAdapter<String> musicAdapter = new ArrayAdapter<String>(getBaseContext(), R.layout.list_songs, listOfMp3s);
//list.setAdapter(listOfMp3s);
}
Have a look a the simple and straight forward tutorial How to create a ListView using ArrayAdapter in Android.
You need to generate a String array and attach the array to an Array adapter
adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, YourStringArray);
and then plug this adapter to your ListView
yourListView.setAdapter(adapter);
Or you could create your own custom adapter by extending ArrayAdapter<YourItem> and attaching YourItem array to it.
I would suggest you to create a custom ArrayAdapter to populate a ListView from your objects the way you want.
The advantage of this technic is that you gain a Views recycle mechanism that will recycle the Views inside you ListView in order to spend less memory.
In Short you would have to:
1. Create an object that represents your data for a single row.
2. Create an ArrayList of those objects.
3. Create a layout that contains a ListView or add a ListView to you main layout using code.
4. Create a layout of a single row.
5. Create a ViewHolder that will represent the visual aspect of you data row from the stand point of Views.
6. Create a custom ArrayAdapter that will populate the rows according to you needs, in it you will override the getView method to specify exactly what the row data would be.
7. Finally assign this ArrayAdapter to your ListView in onCreate.
You can get an idea of how to implement this by reading this blog post I wrote:
Create a Custom ArrayAdapter

Multiple rows in a single TextView

I have an application that has a Database of vehicles with multiple fields.
I then have a ListView in which I want to display some of the fields.
Currently I have this:
SimpleCursorAdapter vehicleAdapter = new SimpleCursorAdapter(this, R.layout.vehiclerow, vehicleCursor, new String[] {"registration"}, new int[] { R.id.vehicleRow});
And I want to put multiple values on the vehicleRow TextView for instance:
Toyota - Corolla
in which Toyota and Corolla come from separate fields of the database.
I've tried this:
SimpleCursorAdapter vehicleAdapter = new SimpleCursorAdapter(this, R.layout.vehiclerow, vehicleCursor, new String[] {"make", "model"}, new int[] { R.id.vehicleRow});
but it doesn't work.
What could be the problem?
Regards
You can only map one data field to one view with the standard adapters.
You either need to create a custom adapter to let you put two data fields.into one widget (not always trivial) or create a new rowlayout with the necessary textviews and use that with a standard adapter.
I'd go for the second option.
Create another TextView and entered its Id in the cursorAdapter.
try in this way :
String[] from = new String[]{DbManager.Title, DbManager.Date};
int[] to = new int[] { R.id.list_name_main,R.id.list_date_main};{
Adapter = new SimpleCursorAdapter(this, R.layout.row_item_by_list, c1, from, to);
//Adapter.setViewBinder(new ScoreHistoryBinder());
list_item.setAdapter(Adapter);
list_item.setOnItemClickListener(listOnItemClickListener);}

How do you amend a row value before displaying it using ListView and SimpleCursorAdaptor?

I'm using SimpleCursorAdaptor and a ListView to display the values in my SQLite database rows. One of the values in my row is a date (column 'date'). Rather than display this date I need to run this through a method that will return another string based on what the date is. This is the value I want displayed in my list rather than the actual value taken straight from the Database.
In short I wish to display all values from my database table row except for one, where I need to change it before displaying it.
Here is my code:
public class BinCollectionDayListActivity extends ListActivity{
//
private static final String fields[] = { "name", "date", BaseColumns._ID };
//
public void onCreate(Bundle savedInstanceState) {
//
super.onCreate(savedInstanceState);
//
DatabaseHelper helper = new DatabaseHelper(this);
SQLiteDatabase database = helper.getWritableDatabase();
Cursor data = database.query("names", fields, null, null, null, null, null);
CursorAdapter dataSource = new SimpleCursorAdapter(this, R.layout.binrow, data, fields, new int[] { R.id.name, R.id.date });
dataSource.getCursor().requery();
//
ListView view = getListView();
view.setHeaderDividersEnabled(true);
setListAdapter(dataSource);
//
helper.close();
database.close();
}
}
As you can tell I am pretty new to Android development and would love to know what the best approach would be to achieving the desired result.
Thanks in advance,
Tony
Two options that I've used before:
Array Adapter (Preferred):
Create an ArrayAdapter and populate the Cursor data into your ArrayAdapter.
http://anujarosha.wordpress.com/2011/11/17/how-to-create-a-listview-using-arrayadapter-in-android/
ViewBinder: On your Cursor, you can setup/specify a ViewBinder where you can check the data that's about to be mapped, perform some logic on it, and spit out a different result if desired. This is probably exactly what you're looking for, but do consider the ArrayAdapter as it tends to give you better control and it's a pain to switch these things later on.
Changing values from Cursor using SimpleCursorAdapter

Query into list activity with rawquery using multiple tables?

Basicly I have two tables in my database brought together with a rawQuery and a ListActivity that is supposed to pull info from both tables and show it inside of the ListActivity. I don't get a force close or anything the problem is the information does not show up.
MY RAWQUERY
public Cursor fetchName() {
return ourdb.rawQuery("SELECT wwJobTable._id, wwJobTable.JobName, wwLatLonTable.JobLatitude FROM wwJobTable, wwLatLonTable WHERE wwLatLonTable.JobLatitude=wwJobTable.JobCode", null);
}
HOW I AM VIEWING THE TABLE INFORMATION
private void fillData() {
// Get all of the rows from the database and create the item list
mTimeNotesCursor = mDbHelper.fetchName();
mTimeNotesCursor.moveToFirst();
startManagingCursor(mTimeNotesCursor);
// Create an array to specify the fields we want to display in the list (only TITLE)
String[] from = new String[]{WWDatabase.KEY_JOBNAME,
WWDatabase.KEY_LATITUDE};
// and an array of the fields we want to bind those fields to (in this case just text1)
int[] to = new int[]{R.id.textView1, R.id.textView2};
// Now create a simple cursor adapter and set it to display
SimpleCursorAdapter notes =
new SimpleCursorAdapter(this, R.layout.time_text_row, mTimeNotesCursor, from, to);
setListAdapter(notes);
}
What could I possibly be doing wrong?

Listview from multiple tables?

I'd like to populate a listview from 2 tables. Anyone know how I can achieve this? Currently what I have looks like but it only works with one adapter:
private void populate() {
todoCursor = dbNotes.getTodoKey();
startManagingCursor(todoCursor);
todo =
new SimpleCursorAdapter(
this,
R.layout.todo_list,
todoCursor,
new String[] {databaseHelper.DB_COLUMN_TODO_KEYS},
new int[] {R.id.textTodo});
setListAdapter(todo);
}
private void fillData(int i) {
Cursor notesCursor = dbNotes.retrieveAll(i, "=0");
startManagingCursor(notesCursor);
notes =
new SimpleCursorAdapter(
this,
R.layout.list_item,
notesCursor,
new String[] {databaseHelper.DB_COLUMN_SUBJECT, databaseHelper.DB_COLUMN_TIME, databaseHelper.DB_COLUMN_MESSAGE, databaseHelper.DB_COLUMN_DOW, databaseHelper.DB_COLUMN_MD},
new int[] {R.id.text1, R.id.text2, R.id.text3, R.id.textDay, R.id.textDayOfWeek});
setListAdapter(notes);
}
I'd like to populate a listview from 2 tables. Anyone know how I can achieve this?
You haven't exactly explained what you mean by "populate a listview from 2 tables".
So, depending on your definition, you could:
Use a join to create a single result set from both tables
Use my MergeCursor to concatenate adapters on your two result sets into a single adapter
Assemble a single MatrixCursor from your disparate parts that you then put into the list
There are probably other solutions as well.

Categories

Resources