Получить выбранный элемент из ListView, связанного с SimpleCursorAdapter

Я новичок в разработке Android... с iPhone и .Net. Я видел очень похожие вопросы на этот, но ни один из них не касался SimpleCursorAdapter.

У меня есть базовая ListActivity, которая использует курсор для привязки данных из запроса SQLite к моему ListView:

ListAdapter adapter = new SimpleCursorAdapter(
        this, 
        android.R.layout.simple_list_item_1,  
        c,        
        new String[] {"name"},   
        new int[] {android.R.id.text1}); 

setListAdapter(adapter);

Затем, когда элемент нажат:

public void onListItemClick(ListView l, View v, int position, long id) {

    super.onListItemClick(l, v, position,  id);

    //Difference between this:
    Cursor c = (cursor)l.getItemAtPosition(position);
    //and this??
    Cursor c = (Cursor)l.getAdapter().getItem(position);

    int categoryId = c.getInt(0);
}

Это правильный способ получить идентификатор выбранного элемента? Это кажется странным, потому что я бы не подумал, что смогу использовать свой курсор после закрытия базы данных (то есть после привязки). В чем смысл переданного идентификатора, когда я не могу найти способ получить фактический элемент из этого идентификатора? Кроме того, я не понимаю, почему getItemAtPosition() возвращает курсор... курсор привязан ко всему списку; а не один ряд. Наконец, если это правильно, есть ли разница между двумя показанными способами получения курсора? Спасибо.


person GendoIkari    schedule 27.05.2011    source источник


Ответы (2)


Итак, пара моментов: после того, как вы выбрали курсор, вы хотите вызвать startManagingCursor. Это связывает жизненный цикл курсора с жизненным циклом Activity (поэтому, когда Activity уничтожается, курсор закрывается/очищается).

startManagingCursor(c);
ListAdapter adapter = new SimpleCursorAdapter(
        this, 
        android.R.layout.simple_list_item_1,  
        c,        
        new String[] {"name"},   
        new int[] {android.R.id.text1}); 
setListAdapter(adapter);

Кроме того, база данных не закрыта, Cursor обычно поддерживает активное соединение с БД (поэтому ListView может прокручивать и выполнять действия такого рода, которые могут потребовать доступа к содержимому Cursor в будущем.

На ваш основной вопрос самый простой способ сделать это в onListItemClick таков:

Cursor c = ((SimpleCursorAdapter)l.getAdapter()).getCursor();
c.moveToPosition(position);

Затем вы можете использовать c.getLong(0) для получения идентификатора (при условии, что вы выбрали столбец идентификатора в качестве первого столбца, что обычно имеет место). Однако обратите внимание, что идентификатор передается как часть подписи (см. последний аргумент в public void onListItemClick(ListView l, View v, int position, long id)), поэтому вам действительно не нужно извлекать его снова (но вы, безусловно, можете, если хотите сжечь циклы). Для доступа к другим столбцам вы можете сделать то же самое, просто измените индекс столбца.

Надеюсь, это поможет.

person Femi    schedule 27.05.2011
comment
Спасибо! Я вызывал startManagingCursor, но до сих пор не понимал, почему! Пара вопросов... Итак, даже когда я вызываю SQLiteDatabase.close(), это не мешает моему курсору обращаться к нему? И ListView, похоже, не имеет метода getCursor(). Наконец, идентификатор, который передается моему методу, автоматически является идентификатором из моей базы данных? Спасибо! - person GendoIkari; 27.05.2011
comment
Ах, если вы вызовете close, то ваш ListView, вероятно, перестанет функционировать: обычно я повторно использую свой объект приложения в качестве адаптера базы данных: вызываю открытие в onCreate и закрытие в onTerminate, а затем использую это, чтобы связать жизненный цикл подключения к базе данных с приложением. жизненный цикл. Что касается getCursor, моя ошибка: должно быть Cursor c = ((SimpleCursorAdapter)l.getAdapter()).getCursor();. И да, идентификатор — это то, что выходит из базы данных: это довольно удобно. - person Femi; 28.05.2011
comment
startManagingCursor устарел в APi11, вы можете обновить свой ответ, упомянув об использовании CursorLoader - person Noah; 08.06.2011
comment
startManagingCursor устарел только в том случае, если вы нацелены на одного из 0,0001% пользователей Android, у которых есть HoneyComb или ICS, или которые хотят справиться с безумием версионного импорта. - person Bjorn; 03.01.2012
comment
@Femi Как я могу в onListItemClick переключать видимость определенного дочернего элемента макета, который я передал в свой CursorAdapter. Я пробовал TextView mTextView = (TextView) v.findViewById(R.id.my_text); mTextView.setVisibility(mTextView.isShown()? View.GONE: View.VISIBLE); mCursorAdapter.notifyDataSetChanged();, но, похоже, он выбирает, какие элементы списка переключать случайным образом, независимо от того, на какой я нажимаю. - person ababzy; 03.03.2012
comment
Извините, только что заметил комментарий: пара улучшений. 1) onTerminate в объекте Application на самом деле никогда не вызывается, поэтому вам следует использовать отдельный объект менеджера баз данных, который вы создаете в onCreate и закрываете в onDestroy. 2) @ababzy, поскольку представления перерабатываются, вы не можете использовать текущий статус видимости в качестве флага: если вы хотите его настроить, вам нужно настроить его на основе какого-либо другого значения (возможно, взятого из текущего курсора). - person Femi; 07.05.2012
comment
@BjornTipling На самом деле вы можете использовать CursorLoaders с пакетом совместимости, что плохого в обновлении такого замечательного ответа. - person Gaurav Agarwal; 27.05.2012
comment
Просто хотел добавить, что в исходном коде CursorAdapter getItem(position) делает именно это, поэтому в подходе GendoIkari нет ничего плохого. - person Pin; 19.02.2013
comment
Бьорн, startManagingCursor устарел - точка. Это факт, который вряд ли изменится. - person ban-geoengineering; 27.10.2014

По-другому:

listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View arg1, int position, long arg3) {

            Cursor cursor = (Cursor) parent.getAdapter().getItem(position);
            //TODO
            }
});
person Yuliia Ashomok    schedule 15.09.2015