Дополнительно
Следование ответу с использованием ArrayList на самом деле не лучший подход.
Например, вы выбираете ProvinceX из списка и затем вставляете это значение в другую таблицу, затем говоритечто ProvinceX меняет свое имя на ProvinceY, тогда вам нужно обновить ProvinceX на ProvinceY, где бы оно ни использовалось в других таблицах.Не так сложно, но неэффективно и не нормализовано (иначе данные дублируются).
В SQLite, за исключением специальных таблиц, определенных с использованием WITHOUT ROWID, все таблицы имеют специальный, обычно скрытый столбец, называемый ROWID .Содержит целое число (до 64 разрядов со знаком, так что потенциально 9223372036854775807 строк (в два раза больше, если вы используете отрицательные значения)).
Столбец rowid (обычно с псевдонимом (см. Далее)) имеет некоторые преимущества.Его можно рассматривать как индекс MASTER (лучше, чем индекс PRIMARY).Поиск rowid или его псевдонима выполняется быстрее.
Данные для таблиц rowid хранятся в виде структуры B-Tree, содержащей одну запись для каждой строки таблицы, с использованием значения rowidкак ключ.Это означает, что получение или сортировка записей по rowid выполняется быстро.Поиск записи с определенным идентификатором строки или всех записей с идентификаторами строк в указанном диапазоне выполняется примерно вдвое быстрее, чем аналогичный поиск, выполняемый путем указания любого другого PRIMARY KEY или индексированного значения.
Хранилищедля хранения rowid будет меньше, чем a для строки, поэтому при извлечении данных может быть буферизовано больше строк.
Обычно таблица будет иметь псевдоним rowid специально с использованием INTEGER PRIMARY KEY (например, INT PRIMARY KEY не создает псевдоним rowid ).Если вы проверите ответ, то увидите, что в столбце _id (то есть BaseColumns._ID) используется INTEGER PRIMARY KEY.
Таким образом, использование ArrayList может быть неэффективным в качестве единственного способа последующего доступа к данным.из базы данных требует менее эффективного, чем оптимальный, поиск этой строки.
ArrayList
Если бы вы создавали объект Province, который включает переменную-член (поле) для rowid (как правило, его псевдоним) и использование ArrayList в качестве источника для счетчика, тогда использование этого значения может иметь преимущества в плане эффективности (меньше данных для хранения, более быстрый доступ к данным, больше буферизованных данных).
Если это значение хранится в соответствующей таблице, то изменение значения «Провинция Х» на «Провинция» в таблице «Провинция» приведет к изменению этого значения во всем.Так что только 1 обновление.
Таким образом, рабочий пример ниже включает в себя Spinner и Button, которые используют ArrayList (также включен класс Province).
CursorAdapater (SimpleCursorAdapter)
Как вы уже поняли, с помощью Android SQLite SDK / API вы получаете данные в Cursor, и, как подсказывает заголовок этого раздела, есть адаптеры для Cursors для ListViews и Spinners.Использовать их, на мой взгляд, еще проще, и у них есть несколько преимуществ.У них есть методы, которые возвращают _id (должен быть псевдонимом столбца rowid ). ЕСЛИ ЭТО ВАЖНО ДЛЯ АДАПТЕРОВ КУРСОРА, столбец определенно называется _id (следовательно, константа BaseColumns._ID).Адаптер курсора вылетит, если такой колонки нет.Результаты непредсказуемы, если столбцы не являются псевдонимами столбца rowid .
- Infact ArrayAdapters также имеют обработку идентификаторов, например, существует getSelectedItemId () .Тем не менее, это вернет позицию не как целое число, а как долго, onItemClickListeners также будет включать значение в качестве 4-го параметра (опять же, поскольку курсор отсутствует, значение - это позиция выбранного элемента).
В качестве такового вы можете рассмотреть следующий пример / демонстрацию, в которой есть 3 счетчика и кнопки (оригинальный адаптер ArrayList, Aapter ArrayList и CursorAdapter).
Все три результата выводятся в журнал.
Пример демонстрационного кода
Класс Провинции. Province.java
public class Province {
private long provinceId;
private String provinceName;
public Province(long id, String name) {
this.provinceId = id;
this.provinceName = name;
}
public Province(String name) {
this(-1,name);
}
public Province() {
}
public long getProvinceId() {
return provinceId;
}
public void setProvinceId(long provinceId) {
this.provinceId = provinceId;
}
public String getProvinceName() {
return provinceName;
}
public void setProvinceName(String provinceName) {
this.provinceName = provinceName;
}
@Override
public String toString() {
return this.provinceName; // NOTE overridden to avoid using Custom adapter
}
}
- ничего сверх базового Java в вышеприведенном
макет действия activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<Spinner
android:id="@+id/spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Spinner>
<Button
android:id="@+id/ok_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="OK">
</Button>
<Spinner
android:id="@+id/spinner2"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Spinner>
<Button
android:id="@+id/ok2_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="OK2 (Province ArrayList)">
</Button>
<Spinner
android:id="@+id/spinner3"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Spinner>
<Button
android:id="@+id/ok3_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="OK3 (Cursor)">
</Button>
</LinearLayout>
- Два дополнительных счетчика и кнопки
Расположение Spinner (без изменений, поэтому не отображается)
Помощник по базам данных
Помощник базы данных из исходного ответа имеет два дополнительных метода согласно
//<<<<<<<<<< ADDITIONAL FOR ArrayList<Province> adapter
public ArrayList<Province> getAllProvicesAsProvinceObjects() {
ArrayList<Province> rv = new ArrayList<>();
Cursor csr = mDB.query(TABLENAME_PROVINCE,null,null,null,null,null,COL_PROVINCE_NAME);
while (csr.moveToNext()) {
rv.add(
new Province(
csr.getLong(csr.getColumnIndex(COL_PROVINCE_ID)),
csr.getString(csr.getColumnIndex(COL_PROVINCE_NAME))
)
);
}
csr.close(); //<<<<<<<<<< should always close cursors when done with them
return rv;
}
//<<<<<<<<<< ADDITIONAL FOR Cursor adapter
public Cursor getAllProvincesAsCursor() {
return mDB.query(TABLENAME_PROVINCE,null,null,null,null,null,null);
}
- Первый getAllProvicesAsProvinceObjects () возвращает ArrayList
- Второй возвращает Cursor (поэтому нет необходимости создавать промежуточный ArrayList) +1 для Cursor Adapter, который легче кодировать.
Активность MainActivity.java
У этого есть три из большинства частей кода.
Обратите внимание на управление ?????? методы, извлекать последние данные, создавать Spinner (один раз) и управлять (вызываясь согласно методу onResume в конце) обновлением списка (сообщить адаптеру, что данные изменились).
public class MainActivity extends AppCompatActivity {
DatabaseHelper datahelper;
Spinner spinner1,
spinner2, //<<<<<<<<<<ADDITONAL For ArrayList<Province> adapter
spinner3 //<<<<<<<<<<ADDITIONAL for Cursor adapter
;
Button ok_button,
ok2_button, //<<<<<<<<<<ADDITIONAL For ArrayList<Province> adapter
ok3_button //<<<<<<<<<<ADDITIONAL for Cursor adapter
;
ArrayAdapter<String> adapter; //<<<<<<<<<< declares the adapter at class level
ArrayList<String> list; //<<<<<<<<<< declares at the class level
ArrayAdapter<Province> adapter2; //<<<<<<<<<<ADDITIONAL For ArrayList<Province> adapter
ArrayList<Province> list2; //<<<<<<<<<< ADDITIONAL For ArrayList<Province> adapter
SimpleCursorAdapter adapter3; //<<<<<<<<<<ADDITIONAL for Cursor adapter
Cursor mCsr; //<<<<<<<<<<ADDITIONAL for Cursor adapter
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
datahelper = new DatabaseHelper(this);
loadDataForDemo(); //<<<<<<<<<< load some data for the demo
spinner1=(Spinner)findViewById(R.id.spinner);
spinner2 =(Spinner) findViewById(R.id.spinner2); //<<<<<<<<<< For ArrayList<Province> adapter
spinner3 = (Spinner) findViewById(R.id.spinner3); //<<<<<<<<<<ADDITIONAL for Cursor adapter
list=datahelper.getAllProvinces(); //<<<<<<<<<< CHANGED to use already decalred
adapter=new ArrayAdapter<String>(this, R.layout.spinner_layout, R.id.text, list); // <<<<<<<<< CHANGED to use already decalred
spinner1.setAdapter(adapter);
ok_button=findViewById ( R.id.ok_button );
ok_button.setOnClickListener ( new View.OnClickListener () {
@Override
public void onClick(View v) {
Ok_button_onClick (v);
}
} );
manageSpinner2(); //<<<<<<<<<< For ArrayList<Province> adapter
ok2_button = findViewById(R.id.ok2_button);
ok2_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Ok_button2_onClick(v);
}
});
manageSpinner3(); //<<<<<<<<<<ADDITIONAL for Cursor adapter
ok3_button = findViewById(R.id.ok3_button);
ok3_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Ok_button3_onClick(v);
}
});
}
//<<<<<<<<<< For ArrayList<Province> adapter >>>>>>>>>>
private void manageSpinner2() {
list2 = datahelper.getAllProvicesAsProvinceObjects();
if (adapter2 == null) {
adapter2 = new ArrayAdapter<>(this,R.layout.spinner_layout,R.id.text,list2);
spinner2.setAdapter(adapter2);
} else {
// Note this applies any changed data (updates, insert, deletes)
adapter2.clear();
adapter2.addAll(list2);
adapter2.notifyDataSetChanged();
}
}
//<<<<<<<<<<ADDITIONAL for Cursor adapter >>>>>>>>>>
private void manageSpinner3() {
mCsr = datahelper.getAllProvincesAsCursor();
if (adapter3 == null) {
adapter3 = new SimpleCursorAdapter(
this,
R.layout.spinner_layout,mCsr,
// Note following arrays should have matching number of elements
new String[]{DatabaseHelper.COL_PROVINCE_NAME}, // columns to get data from
new int[]{R.id.text}, // view id's (TextViews) into which data goes
// Note SimpleCursorAdapter quite flexible as layout can have multiple column/view matchings
0
);
spinner3.setAdapter(adapter3);
} else {
adapter3.swapCursor(mCsr);
}
}
private void Ok_button_onClick(View v) {
String value_via_position = list.get(spinner1.getSelectedItemPosition());
String value_from_selected_item = (String) spinner1.getSelectedItem();
Log.d("SELECTED","Selected item is " + value_via_position + " according to position.");
Log.d("SELECTED","Selected item is " + value_from_selected_item + " as per the selected item method");
long id_of_province1 = datahelper.getProvinceIdFromName(value_via_position);
long id_of_province2 = datahelper.getProvinceIdFromName(value_from_selected_item);
Log.d ("SELECTED","ID (via position) is " + String.valueOf(id_of_province1) + " ID (via selected item) is " + String.valueOf(id_of_province2));
}
private void loadDataForDemo() {
// Only load provinces if none exist
if (DatabaseUtils.queryNumEntries(datahelper.getWritableDatabase(),DatabaseHelper.TABLENAME_PROVINCE) > 0) return;
String[] provinces_to_load = new String[]{
"Hereington",
"Nothereington",
"Nowherington",
"Somewhereington",
"Overthereington",
"Inthehaystackington",
"Noweheretobefoundington",
"Atsomeplaceington",
"Zeroington",
"Beforetheotherplacington"
};
for (String province: provinces_to_load) {
datahelper.addProvince(province);
}
}
//<<<<<<<<<< For OK2 button
private void Ok_button2_onClick(View v) {
Province thisProvince = (Province) spinner2.getSelectedItem();
long id = ((Province) spinner2.getSelectedItem()).getProvinceId();
//spinner2.getSelectedItemId()
String name = ((Province) spinner2.getSelectedItem()).getProvinceName();
Log.d("SELECTED2",
"You selected Province:-" +
" ID=" + String.valueOf(thisProvince.getProvinceId()) +
" Name=" + thisProvince.getProvinceName());
}
private void Ok_button3_onClick(View v) {
long id = spinner3.getSelectedItemId(); // Cursor Adapter knows the id
String name = mCsr.getString(mCsr.getColumnIndex(DatabaseHelper.COL_PROVINCE_NAME));
Log.d("SELECTED3","You clicked ID=" + String.valueOf(id) + " Name="+name);
}
@Override
protected void onResume() {
super.onResume();
manageSpinner2(); //<<<<<<<<<< will apply changed data when returning to the activity
manageSpinner3(); //<<<<<<<<<<< likewise for Cursor adapter
}
}