Ошибка SimpleCursorAdapter: столбец не существует — происходит только в Android 2.1

У меня есть активность, которая расширяет ExpandableListActivity. У меня нет проблем, когда я запускаю приложение на Android 2.2+. Однако, когда я запускаю его на эмуляторе Android 2.1, это действие принудительно закрывается (у других действий в приложении нет проблем). Я совершенно озадачен.

Я создал собственный адаптер для использования с ExpandableListView, расширяющим SimpleCursorTreeAdapter. Я настраиваю адаптер списка, используя следующий код:

customExpandableListAdapter = new BeerFlightsExpandableListAdapter(
                                    this,                                           // context
                                    beerFlights,                                    // cursor
                                    R.layout.beer_flight_list_item,                 // group layout
                                    new String[]{"_id", "name"},                    // group FROM
                                    new int[] {R.id.flight_id, R.id.flight_name},   // group TO
                                    R.layout.beer_flight_beer_list_item,            // child layout
                                    new String[]{"_id", "name"},                    // child FROM
                                    new int[]{R.id.beer_id, R.id.beer_name});       // child TO
setListAdapter(customExpandableListAdapter);

Я использую следующий код для получения курсора group:

String sql =
        "SELECT beer_flights._id, beer_flights.name, COUNT(beer_flight_beers.beer_id) AS beer_count"+
        " FROM beer_flight_beers"+
            " INNER JOIN beer_flights ON beer_flight_beers.beer_flight_id = beer_flights._id"+
            " INNER JOIN beer_locations ON beer_flights.location_id = beer_locations.location_id AND beer_locations.beer_id = beer_flight_beers.beer_id"+
        " WHERE beer_flights.location_id = ?"+
        " GROUP BY beer_flights._id"+
        " ORDER BY beer_flights.priority ASC";

Cursor cur = db.rawQuery(sql, new String[]{ locationId.toString() });

Я использую следующий код для получения курсора child:

String sql =
        "SELECT DISTINCT beers._id, beers.name, beers.brewery"+
        " FROM beer_flight_beers"+
            " INNER JOIN beers ON beer_flight_beers.beer_id = beers._id"+
            " INNER JOIN beer_flights ON beer_flight_beers.beer_flight_id = beer_flights._id"+
            " INNER JOIN beer_locations ON beer_flights.location_id = beer_locations.location_id AND beer_flight_beers.beer_id = beer_locations.beer_id"+
        " WHERE beer_flight_beers.beer_flight_id = ?"+
        " ORDER BY beers.name ASC";

Cursor cur = db.rawQuery(sql, new String[]{ flightId.toString() });

Как я уже сказал, это отлично работает в эмуляторах для Android 2.2+, а также на моем Droid 2 под управлением 2.3.3 и моем Droid 4 под управлением 2.3.6. Однако, когда я запускаю тот же код в эмуляторе Android 2.1, я получаю следующую ошибку:

Uncaught handler: thread main exiting due to uncaught exception
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.absolutemg.jlbeers/com.absolutemg.jlbeers.BeerFlights}:
java.lang.IllegalArgumentException: column 'name' does not exist

[snip]

Caused by: java.lang.IllegalArgumentException: column 'name' does not exist
at android.database.AbstractCursor.getColumnIndexOrThrow(AbstractCursor.java:314)
at android.widget.SimpleCursorTreeAdapter.initFromColumns(SimpleCursorTreeAdapter.java:194)
at android.widget.SimpleCursorTreeAdapter.initGroupFromColumns(SimpleCursorTreeAdapter.java:200)
at android.widget.SimpleCursorTreeAdapter.init(SimpleCursorTreeAdapter.java:180)
at android.widget.SimpleCursorTreeAdapter.<init>(SimpleCursorTreeAdapter.java:169)
at com.absolutemg.jlbeers.BeerFlights$BeerFlightsExpandableListAdapter.<init>(BeerFlights.java:395)
at com.absolutemg.jlbeers.BeerFlights.onCreate(BeerFlights.java:100)

Оба курсора имеют столбцы _id и name. Поэтому я не уверен, почему я получаю сообщение об ошибке, говорящее, что column 'name' does not exist.

Я изменил некоторые вещи, чтобы изменить курсор parent, чтобы он возвращал столбцы flight_id и flight_name, и соответствующим образом изменил адаптер списка. Когда я это сделал, активность больше не падала. Он отображал имена моих групп. Однако, когда я нажал на одну из групп, чтобы открыть ее, она снова закрылась.

Эти же изменения привели к принудительному закрытию активности в Android 2.2+ (я предполагаю, что у меня нет столбца с именем _id в моем курсоре). Так что это действительно не исправление.

Что-то изменилось с курсорами или функцией rawQuery() в версии 2.1, которая была изменена в версии 2.2? Я в полной растерянности, как решить эту проблему.

Я бы хотел отказаться от поддержки Android 2.1 для этого приложения, но у нас есть несколько пользователей, использующих 2.1 (это всего около 1,26% нашей пользовательской базы, но я не хочу никого исключать из обновленного приложения).

Ни один из других вопросов, которые я нашел здесь, в SO, не был таким же, как этот, и мне не повезло найти что-либо еще. Любые идеи?


person Becky    schedule 10.08.2012    source источник
comment
2.1 может иметь версию sqlite, отличную от более новых телефонов, с другими требованиями. Я полагаю, вы уже проверили, что регистр и что имя таблицы является именем в нижнем регистре?   -  person znat    schedule 10.08.2012
comment
Ага... случай sql-запроса правильный. Оказалось, что мне нужно сделать beer_flights.name as name в моем запросе. Не уверен, почему. Может быть, потому что перед ним стоит имя таблицы. ???   -  person Becky    schedule 10.08.2012


Ответы (1)


Мне удалось исправить положение... всего через несколько минут после публикации. И решение заставляет меня чувствовать себя дураком. :(

Я изменил запросы для своих курсоров, чтобы явно указать имя столбца, например:

Групповой курсор

SELECT beer_flights._id AS _id, beer_flights.name AS name, COUNT(beer_flight_beers.beer_id) AS beer_count

Дочерний курсор

SELECT DISTINCT beers._id AS _id, beers.name AS name, beers.brewery AS brewery

После того, как я это сделал, все заработало, как и предполагалось, во всех версиях Android, которые я тестировал.

Кто-нибудь знает, ПОЧЕМУ мне нужно сделать это для Android 2.1, но не для более поздних версий? Мне это кажется глупым, но именно это исправило ситуацию.

Возможно, это произошло из-за того, что в запросе имена таблиц предшествуют столбцам. Это мое единственное предположение на данный момент.

person Becky    schedule 10.08.2012
comment
По моему опыту, Android 2.1 имеет ошибочную реализацию Sqlite. У меня были JOIN, которые совершенно не работали в 2.1, но отлично работали в 2.2+. Кроме того, поскольку вы решили проблему, вы должны принять свой ответ. - person thatsmydoing; 10.08.2012