Dynamically refresh ListView with CursorAdapter

Search This thread

djolec987

New member
Apr 9, 2014
2
0
Hi everyone,
First of all, I'd like to apologize if I'm posting this in a wrong place... This is my first post, I'm still getting familiar with this forum.
I would also like to apologize for the lengthy post.

The title, to a certain extent, reflects what my problem is, but to clarify:

I'm learning Android, so I'm making a simple SMS app for practice.
In it, I have a database which has tables for sent messages, received messages and contacts. I have 3 separate activities (which do NOT extend ListActivity) which show lists for sent messages, received messages and contacts, respectively. The lists are populated through CursorAdapter.

Let's consider the activity for contacts...
In it I have list (ListView) which displays contacts (each list element displays name and phone number). Below the list I have a "Add Contact" button. When I click the button a dialog pops up and shows the form for adding new contact. The buttons in the dialog preform all the database operations.
Similarly, when I click some item in the ListView, another dialog pops up. That dialog has buttons for "Send SMS", "Edit" and "Delete" contact. Again, the buttons do all the work with the database.

The trouble:

My trouble is... When I add a new contact, or delete one (after both operations their dialogs dismiss), the ListView is not refreshed.
In order to see the refreshed list I need to close the activity and start it again.
I googled and googled this for 3 days now, and all the answers I found say that I need to call
Code:
adapter.notifyDataSetChanged
and
Code:
adapter.changeCursor
but that doesn't do the trick.

I'll now post the relevant code with the two methods mentioned above. I placed them where i thought they should be, but this doesn't work.
So, I humbly beg someone to guide me through this ordeal.

Many thanks in advanced!

Here comes the code:

The Adapter:

Code:
public class AdapterContactListView extends CursorAdapter {	
	
	private MyDatabaseHelper mdbh;
	private LayoutInflater myLayoutInflater;
	
	public AdapterContactListView(Context context, Cursor c, int flags) {
		super(context, c, flags);
		mdbh = MyDatabaseHelper.getMyDatabaseHelper(context);
		myLayoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);		
	}	
	
	@Override
	public void bindView(View view, Context context, Cursor cursor) {
		// TODO Auto-generated method stub
		TextView fullNameTV = (TextView)view.findViewById(R.id.contactElementNameTV);
		TextView phoneNumberTV = (TextView)view.findViewById(R.id.contactElementNumberTV);
		String fullName = cursor.getString(cursor.getColumnIndex(mdbh.getContactFirstName()));
		fullName = fullName.concat(" ");
		fullName = fullName.concat(cursor.getString(cursor.getColumnIndex(mdbh.getContactLastName())));
		String phoneNumber = cursor.getString(cursor.getColumnIndex(mdbh.getContactPhoneNumber()));
		fullNameTV.setText(fullName);
		phoneNumberTV.setText(phoneNumber);		
	}
	@Override
	public View newView(Context context, Cursor cursor, ViewGroup parent) {
		// TODO Auto-generated method stub
		return myLayoutInflater.inflate(R.layout.contact_element, parent, false);
	}
}


And the Activity:

Code:
public class ContactsActivity extends Activity {
	
	
	private MyUtilities myUtilities;
	private MyDatabaseHelper mdbh;
	private AdapterContactListView contactsAdapter;
	private ListView contactsListView;	
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_contacts);
		mdbh = MyDatabaseHelper.getMyDatabaseHelper(this);
		myUtilities = new MyUtilities(this);	
		contactsAdapter = new AdapterContactListView(this,mdbh.getContactsCursor(),CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
		contactsListView = (ListView)findViewById(R.id.contactActivityLV);
		contactsListView.setAdapter(contactsAdapter);
		contactsListView.setOnItemClickListener(new OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parent, View view, int position,	long id) {
				// TODO Auto-generated method stub
				TextView phoneNumberTV = (TextView)view.findViewById(R.id.contactElementNumberTV);				
				String phoneNumber = phoneNumberTV.getText().toString();
				Contact contact = mdbh.getContactFromPhoneNumber(phoneNumber);				
				Dialog d = myUtilities.createSelectedContactOptionsDialog(contact);
				d.show();
				contactsAdapter.changeCursor(mdbh.getContactsCursor());
				contactsAdapter.notifyDataSetChanged();
			}
		});
	}

	public void addContact(View view) {
		Dialog d = myUtilities.createAddContactDialog();
		d.show();
		contactsAdapter.changeCursor(mdbh.getContactsCursor());
		contactsAdapter.notifyDataSetChanged();
	}
}
 
Last edited:

deanwray

Senior Member
Apr 2, 2006
1,145
427
www.deanwray.co.uk

Well notifyDatasetChanged only informs the adapter that the backing interface has new data... but your backing it with a cursor... so in your case it would just cause getView/bindView to be called for all current visible items, thus fire a query at the cursor. I think the cursor will cache the data so it's really a reload on the cursor data and then an adapter notify call you want... If you use loader (depending on target api version) then it should do most of this for you. As it stands if you want to do it manually make sure the cursor is a new cursor of the database that has changed.

(typed in a rush)