Заполнение Spinner Из Базы Данных SQLite Android

Я пытаюсь сделать динамическое выпадающее меню, которое будет заполнено таблицей SQLite. У меня есть объект курсора, из которого я могу вытащить нужные мне данные. Я смог выполнить загрузку значений в раскрывающийся список с помощью кода ниже:

Spinner s = (Spinner) findViewById(R.id.spinner);
    ArrayAdapter adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    s.setAdapter(adapter);

    try{
        Cursor cursor = getAccounts();
        int accountnameIndex = cursor.getColumnIndexOrThrow(ACCOUNT_NAME);
        if(cursor.moveToFirst()){
            do{
                adapter.add(cursor.getString(accountnameIndex));
            } while(cursor.moveToNext());
        }
    } finally {
        MintLink.close();
    }

моя проблема в том, что мне нужен выбор из выпадающего списка, чтобы также содержать RowID выбранного элемента. Мне нужно иметь возможность выбрать один пункт и иметь доступ к значению этого элемента в задней части. Например, думаю, что выпадающего списка в HTML. Каждый выпадающий выбор имеет свое собственное скрытое значение, которое вытягивается. Мне нужно, чтобы это значение было скрыто для меня, чтобы я знал, какой идентификатор они выбирают.

4 ответов


попробуйте использовать SimpleCursorAdapter вместо копирования всех данных вручную в ArrayAdapter.


Это старый вопрос, но первый, который я нашел при выяснении этой проблемы. Вот подробное объяснение с полным источником, который может сократить некоторую работу ног.

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

1) при создании курсора сделать конечно, запрос возвращает поле под названием "_id". Это поле не должно отображаться нигде, но его значение будет возвращено при выборе элемента списка.

2) при создании SimpleCursorAdapter вам необходимо указать идентификаторы макета TextView, где будет размещен текст строки. При использовании android поставляется макет android.R. макет.simple_spinner_item идентификатор текста, который вам нужно использовать, - android.R.id.text1.

Main.в XML

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <Spinner
        android:id="@+id/spinner1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        ></Spinner>
</RelativeLayout>

код операции:

public class TesterActivity extends Activity {
public Context mContext;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // just for this example:
    // create database table with an id field and a text field and add some data
    class MyDBHelper extends SQLiteOpenHelper {
        public MyDBHelper(Context context) {
            super(context, "someDB", null, 2);
        }
        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL("CREATE TABLE someTable (someIDF INTEGER, someTextF TEXT)");
        }
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            db.execSQL("DROP TABLE IF EXISTS someTable");
            onCreate(db);
            db.execSQL("INSERT INTO someTable (someIDF, someTextF) VALUES (54, 'Some text')");
            db.execSQL("INSERT INTO someTable (someIDF, someTextF) VALUES (99, 'Some more text')");
            db.execSQL("INSERT INTO someTable (someIDF, someTextF) VALUES (173, 'Even more text')");
        }
    }
    SQLiteDatabase db = new MyDBHelper(this).getWritableDatabase();

    // get a cursor from the database with an "_id" field
    Cursor c = db.rawQuery("SELECT someIDF AS _id, someTextF FROM someTable", null);

    // make an adapter from the cursor
    String[] from = new String[] {"someTextF"};
    int[] to = new int[] {android.R.id.text1};
    SimpleCursorAdapter sca = new SimpleCursorAdapter(this, android.R.layout.simple_spinner_item, c, from, to);

    // set layout for activated adapter
    sca.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 

    // get xml file spinner and set adapter 
    Spinner spin = (Spinner) this.findViewById(R.id.spinner1);
    spin.setAdapter(sca);

    // set spinner listener to display the selected item id
    mContext = this;
    spin.setOnItemSelectedListener(new OnItemSelectedListener() {
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id){
            Toast.makeText(mContext, "Selected ID=" + id, Toast.LENGTH_LONG).show();
        }
        public void onNothingSelected(AdapterView<?> parent) {}
        });
    }
}

вот еще один ответ с загрузчиками и курсорами.

в создании activity / fragment (указанный фрагмент / activity должен реализовать LoaderManager.LoaderCallbacks<Cursor>):

final Spinner spinner = (Spinner) findViewById(R.id.spinner);
mAdapter = new MyCursorAdapter(getActivity());
spinner.setAdapter(mAdapter);
getLoaderManager().initLoader(SOME_INT_CONSTANT, null, this);

в вашей деятельности/фрагмент:

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    return new MyCursorLoader(getActivity(), args);
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    mAdapter.swapCursor(data);
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
    mAdapter.swapCursor(null);
}

вот адаптер курсора:

class MyCursorAdapter extends CursorAdapter {
    class ViewsHolder {
        TextView text1, text2;
    }

    public MyCursorAdapter(Context context, Bundle args) {
        super(context, null, false);
        // do something with args
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        View v = LayoutInflater.from(context).inflate(R.layout.your_item_layout, parent, false);
        ViewsHolder holder = new ViewsHolder();
        holder.text1 = (TextView) v.findViewById(R.id.text1);
        holder.text2 = (TextView) v.findViewById(R.id.text2);
        v.setTag(holder);
        return v;
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        ViewsHolder holder = (ViewsHolder) view.getTag();
        String text1 = cursor.getString(cursor.getColumnIndex(KEY_TEXT1));
        String text2 = cursor.getString(cursor.getColumnIndex(KEY_TEXT2));
        holder.text1.setText(text1);
        holder.text2.setText(text2);
    }
}

вот загрузчик курсор:

public class MyCursorLoader extends CursorLoader {
    private final YourSQLiteDbAdapter mHelper;

    public MyCursorLoader(Context context) {
        super(context);
        mHelper = new YourSQLiteDbAdapter(context);
        mHelper.openReadOnly();
    }

    @Override
    public Cursor loadInBackground() {
        return mHelper.selectYourDataAsACursor();
    }

    @Override
    protected void onStopLoading() {
        super.onStopLoading();
        mHelper.close();
    }
}

используя это, вы получаете:

  • не использовать устаревшие API
  • использование API загрузчика
  • подгонянные переходники / макеты
  • посмотреть рециркулируя
  • API Уровень 4 обратная совместимость (через поддержку lib)
  • фоновая загрузка данных потока

пример привязки данных можно найти здесь.

http://developer.android.com/guide/topics/ui/binding.html

проверьте раздел "заполнение макета данными" для использования SimpleCursorAdapter