【问题标题】:Populating Spinner From SQLite Database Android从 SQLite 数据库 Android 填充微调器
【发布时间】:2011-01-12 21:03:00
【问题描述】:

我正在尝试制作一个将由 SQLite 表填充的动态下拉列表。我有一个 Cursor 对象,我可以从中提取我需要的数据。我已经能够使用以下代码将值加载到下拉列表中:

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 中的下拉菜单。每个下拉选择都有自己的隐藏值被拉出。我需要隐藏这个值,以便我知道他们选择了哪个 ID。

【问题讨论】:

标签: database android sqlite spinner


【解决方案1】:

尝试使用SimpleCursorAdapter,而不是将所有数据手动复制到ArrayAdapter

【讨论】:

  • 虽然这就是答案。实现 SimpleCursorAdapter 以与 Spinner 一起工作的细节是什么?我需要抽象自己的 ViewBinder 还是可以直接将 SimpleCursorAdapter 与 Spinner 一起使用。
  • 没有办法在摘要中回答这个问题。如果有帮助,我可以为您指出一些示例代码(尽管它从 ContentProvider 而非 SQLite 获取游标):github.com/commonsguy/cw-advandroid/tree/master/Contacts/…
  • 为什么我现在会收到 SimpleCursorAdapter 已弃用警告。现在用什么
  • @DevZer0: SimpleCursorAdapter 未被弃用。但是,他们确实弃用了其中一个构造函数。还有另一个非常相似的构造函数,最后有一个额外的int flags 参数,如果您的android:minSdkVersion 设置为11 或更高,您可以使用它。如果您的 android:minSdkVersion 低于此值,我现在只坚持使用已弃用的构造函数。
【解决方案2】:

可以在此处找到数据绑定示例。

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

检查“用数据填充布局”部分以了解 SimpleCursorAdapter 的用法

【讨论】:

    【解决方案3】:

    这是一个老问题,但我在解决这个问题时发现的第一个问题。这是完整来源的详细解释,可能会减少一些工作量。

    答案确实使用SimpleCursorAdapter,它处理字符串列表,而且还针对选择行时返回的匹配ID字段具有特殊处理。完成这项工作的关键是了解以下两个晦涩的信息:

    1) 创建游标时,请确保查询返回标题为“_id”的字段。该字段不需要显示在任何地方,但它的值将在选择列表项时传回。

    2) 创建 SimpleCursorAdapter 时,您需要提供将放置行文本的 TextView 布局 ID。如果使用 android 提供的布局 android.R.layout.simple_spinner_item,您需要使用的文本 id 是 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) {}
            });
        }
    }
    

    【讨论】:

    • 在我的项目中有效,但仅适用于吐司。如何将 id 保存到 sqlite @MindSpiker?
    【解决方案4】:

    这是加载器和游标的另一个答案。

    在activity/fragment创建中(所说的fragment/activity必须实现LoaderManager.LoaderCallbacks&lt;Cursor&gt;):

    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 向后兼容(通过支持库)
    • 后台线程数据加载

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多