3

So I've got a ListView (using a ListActivity) that I'm populating from a SQLiteDatabase. I'm trying to attach the ID (PK) of the row to the view, so that onListItemClick of each list item, I can do stuff with that ID.

I've read that arbitrary data can be set to a View using setTag and retrieved with getTag(I haven't actually had this work successfully yet, so this may be the problem). Here's a pared down version of what I'm using (for simplicity/brevity):

public class Favorites extends ListActivity {   
    public void onCreate(Bundle savedInstanceState){        
        super.onCreate(savedInstanceState);
        FavoritesDB db = FavoritesDB.getInstance(this);     
        Cursor c = db.fetchFavorites();
        startManagingCursor(c);     
        String[] columns = new String[] { "_id" };
        int[] to = new int[] { R.id.word };         
        SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.favorite, c, columns, to);     
        adapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
            public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
                view.setTag(cursor.getInt(0));
                return true;
            }
        });
        setListAdapter(adapter);        
    }   
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        Object wordID = v.getTag();
        Toast.makeText(getBaseContext(), "ID=" + wordID, 1).show();
    }       
}

The ListView is being populated, and the Toast does show up, but it's always "ID=null", so apparently the ID isn't being set in the ViewBinder call to setTag(or isn't being retrieved property with getTag).

user
  • 86,916
  • 18
  • 197
  • 190
momo
  • 3,885
  • 4
  • 33
  • 54
  • onListItemClick, I want to be able to work with a piece of arbitrary data assigned to the list item (in this example, the ID (Primary Key) of the SQLite row that assigned the data). – momo Dec 05 '11 at 10:56

2 Answers2

2

This depends on your implementation of R.layout.favorite. If you have this layout contains a parent view with child TextViews for e.g. the tag you set is for the TextViews while the View v received from the onListItemClick() is the parent View. You need to make sure that you receive the tag for the same view you set by using:

    @Override      
    protected void onListItemClick(ListView l, View v, int position, long id) {
    Object wordID = v.getChild(0).getTag();          
    Toast.makeText(getBaseContext(), "ID=" + wordID, 1).show();      
    }    
Mohamed_AbdAllah
  • 5,311
  • 3
  • 28
  • 47
  • this looks promising. you're correct, the favorite layout is a linearlayout with child textviews. rather than getting the child in the click, is there a way i can set the tag (in the ViewBinder) to the linearlayout parent instead of the textview? is there a reason ViewBinder sets it to the child instead of the "main" container? – momo Dec 05 '11 at 11:12
  • The reason ViewBinder sets it to the child is that ViewBinder is run every time the Adapter fills a view "to" from the cursor columns. I guess you could do this by changing: `view.setTag(cursor.getInt(0));` with `view.getParent().setTag(cursor.getInt(0));` in the ViewBinder – Mohamed_AbdAllah Dec 05 '11 at 11:16
  • 1
    I ended up using a custom adapter, but the information you've given is more valuable than just getting it to work (which your answer does as well) - so thanks very much – momo Dec 05 '11 at 11:20
  • I posted a similar question here: http://stackoverflow.com/questions/8384757/whats-exactly-happening-in-getview if you'd like to take a look – momo Dec 05 '11 at 11:43
0

You probably should get the cursor from the adapter. This way if your cursor gets replaced you are still are still getting a valid cursor.

@Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
       Cursor cursor =  adapter.getCursor();
       cursor.moveToPosition(position);
       String id = cursor.getString(cursor.getColumnIndex("primary key field name in database");
       Toast.makeText(getBaseContext(), "ID=" + id, 1).show();
    } 

NOTE : your adapter must be declared as a SimpleCursorAdapter other wise you should downcast it.

confucius
  • 13,127
  • 10
  • 47
  • 66