В настоящее время я пытаюсь отобразить информацию о базе данных в своем приложении для Android.
Я хочу, чтобы данные отображались в табличной форме:

+----------+----------+-----+----------+
| column 1 | column 2 | ... | column n |
+----------+----------+-----+----------+
| xxxx     | xxxx     | ... | nnnn     |
| yyyy     | yyyy     | ... | nnnn     |
| ....     | ....     | ... | nnnn     |
| zzzz     | zzzz     | ... | nnnn     |
+----------+----------+-----+----------+

Глядя на информацию ЗДЕСЬ, похоже, что я необходимо использовать GridView с SimpleCursorAdapter.

Итак, я создал класс DatabaseHelper, который расширяет SQLiteOpenHelper. В этом классе у меня есть метод, который возвращает курсор для запроса:

public static final String DATABASE_NAME = "myDatabaseName";
public static final int DATABASE_VERSION = 1;
public static final String TABLE_NAME = "myDatabaseTableName";

public DatabaseHelper(Context context){
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

public static final String MY_QUERY = "SELECT * FROM " + TABLE_NAME;

public Cursor getDataCursor(){
    SQLiteDatabase sqliteDB = this.getReadableDatabase();
    return sqliteDB.rawQuery(MY_QUERY, null);
}

В одном из разделов «учебника» на этой странице Google Dev говорится:

Например, если вы хотите создать список имен людей и номеров телефонов, вы можете выполнить запрос, который возвращает Cursor, содержащий строку для каждого человека и столбцы для имен и номеров. Затем вы создаете массив строк, определяющий, какие столбцы из Курсора вы хотите в макете для каждого результата, и целочисленный массив, определяющий соответствующие представления, в которые должен быть помещен каждый столбец.

Тогда есть этот код:

String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER};
int[] toViews = {R.id.display_name, R.id.phone_number};

Итак, в моем MainActivity.java я создаю новый экземпляр моего DatabaseHelper и получаю курсор:

DatabaseHelper myDBHelper = new DatabaseHelper(this);
Cursor myDataCursor = myDBHelper.getDataCursor();

Я не могу понять, что такое "ContactsContract" в приведенном выше фрагменте Google? Я подумал, что это может быть их Cursor, но у моего курсора нет доступных ему методов «Data» или «CommonDataKinds». Я немного покопался на страницах руководств по API Google, чтобы увидеть, где они определили эти методы, но не могу их найти. Я также не могу понять, где они взяли "R.layout.person_name_and_number" в том же примере.

Спасибо, что нашли время прочитать.

РЕДАКТИРОВАТЬ:

Я добавил этот код в свой код в MainActivity.java:

DatabaseHelper myDBHelper = new DatabaseHelper(this);
Cursor myDataCursor = myDBHelper.getDataCursor();
String[] fromColumns = {"_id", "columnA","columnB","...","columnN"};
int[] toViews = {R.id.id_textview, R.id.columnA_textview, R.id.columnB_textview, ... , R.id.columnN_textview};
SimpleCursorAdapter sca = new SimpleCursorAdapter(this, R.layout.my_new_layout, myDataCursor, fromColumns, toViews, 0);
ListView myListView = (ListView) findViewById(R.id.row_of_data);
myListView.setAdapter(sca);

И я создал новое представление под названием my_new_layout.xml:

<ListView android:id="@+id/row_of_data">
    <TextView android:id="@+id/id_textview" />
    <TextView android:id="@+id/columnA_textview" />
    <TextView android:id="@+id/columnB_textview" />
    ...
    <TextView android:id="@+id/columnN_textview" />
</ListView>

А затем я добавил свое новое представление в activity_main.xml

<include layout="@layout/"my_new_layout />

Однако теперь, когда я пытаюсь запустить приложение, я получаю сообщение об ошибке:

java.lang.unsupportedoperationexception addview(view, layoutparams) is not supported in adapterview

И я получаю эту ошибку, как ни странно, когда включаю свой новый макет в activity_main.xml.

2
Brian 28 Дек 2015 в 18:16

2 ответа

Лучший ответ

Просматривая документацию для SimpleCursorAdapter и его конструктора, вы может видеть

public SimpleCursorAdapter (Context context, int layout, Cursor c, String[] from, int[] to, int flags)

Параметры

  • context: контекст, в котором выполняется ListView, связанный с этой SimpleListItemFactory.
  • layout: идентификатор ресурса файла макета, который определяет представления для этого элемента списка. Файл макета должен включать как минимум те именованные представления, которые определены в "to"
  • c: курсор базы данных. Может иметь значение null, если курсор еще недоступен.
  • from: список имен столбцов, представляющих данные для привязки к пользовательскому интерфейсу. Может иметь значение null, если курсор еще недоступен.
  • to: представления, которые должны отображать столбец в параметре "from". Все это должны быть TextView. Первым N представлениям в этом списке присваиваются значения первых N столбцов в параметре from. Может иметь значение null, если курсор еще недоступен.
  • flags: флаги, используемые для определения поведения адаптера в соответствии с CursorAdapter (Context, Cursor, int).

fromColumns - это имена столбцов вашей таблицы, из которых вы хотите получать данные.

toViews - это идентификаторы ваших TextView, которые должны быть внутри XML-макета для вашей строки (второй параметр в конструкторе - int layout).

Количество элементов в обоих массивах должно быть одинаковым.

1
Marko 28 Дек 2015 в 15:29

Прежде всего, ваша команда SQL не должна быть такой. "SELECT * FROM MyDatabase";

Либо имя вашей таблицы вводит в заблуждение, либо в вашей логике есть ошибка.

"SELECT * FROM MyDatabase"; должно быть (логически) "SELECT * FROM MyTable";

Возможно, поэтому ваш курсор не возвращает то, что вы ожидаете.


Что касается ContactsContract.CommonDataKinds.Phone.NUMBER, это просто статический класс, содержащий константы.

Следующий шаблон позволяет вам иметь класс со всеми вашими строками в организованном месте.

Это также поможет вам, разрешив автозаполнение кода IDE, чтобы вам не приходилось «запоминать» каждое имя переменной / и т. Д. Вы можете просто заполнить их автоматически до завершения. Это помогает централизовать ваши константы и иметь только одно место, где вам нужно изменить строковые значения.

Так, например (и здесь указано только 1 значение)

public class ContactsContract {
    public class CommonDataKinds {
        public class Phone {
            public static final String NUMBER = "number";
        }
    }    

}

Дополнительная информация:

Вот javadoc для рассматриваемого файла:

https://developer.android.com/reference/android/provider/ContactsContract.html

Вот исходный код этого файла (из кода grep):

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.0_r1/android/provider/ContactsContract.java

(И, как вы можете видеть, мой приведенный выше фрагмент кода верен, за исключением того, что я забыл сделать каждый класс final ... но я был близок)


Вот еще один пример, который может быть более понятным:

Я написал этот код (не мое репо ... код находится в репозитории моего консультанта по PhD и использовался в курсе на курсе Coursera) https://www.coursera.org/course/posasoftware)

Наш Схема МООК

Файл, который его использует (общедоступный, и учащимся не нужно писать)

Как видите, преимущество класса схемы состоит в том, что он позволяет второму классу «использовать» внутренние строковые значения схемы без необходимости напрямую обрабатывать строки. Между этими файлами по-прежнему существует тесная связь, но она позволяет вам вносить изменения в БД (например, исправлять опечатку и т.д.) в одном месте, без необходимости просматривать весь код в поисках строк для замены. (также сокращает количество опечаток в других местах кода).

1
mawalker 28 Дек 2015 в 17:00