【问题标题】:Creating 3 spinners that are populated by sqlite database创建由 sqlite 数据库填充的 3 个微调器
【发布时间】:2025-12-23 06:40:06
【问题描述】:

我正在尝试实现一个活动,它有 3 个微调器(下拉列表),每个微调器都由来自 sqlite 数据库的不同表填充。我设法创建了一个正确填充的微调器,但我在创建另外两个并正确填充它们时遇到了麻烦。

这是我目前的主要活动:

public class MainActivity extends Activity implements OnClickListener, OnItemSelectedListener {
private DBManager data;
private SQLiteDatabase db;
private final String DB_NAME = "hanakolfein.s3db";
private Spinner spinner;
List<String> list;
ArrayAdapter<String> adapter;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

      /*Spinner sp1, sp2, sp3;
        sp1 = (Spinner) findViewById(R.id.spinner1);
        sp2 = (Spinner) findViewById(R.id.spinner2);
        sp3 = (Spinner) findViewById(R.id.spinner3);

        sp1.setOnItemSelectedListener(null);
        sp2.setOnItemSelectedListener(null);
        sp3.setOnItemSelectedListener(null); */

    data = new DBManager(this, DB_NAME);
    db = data.openDataBase();


    spinner = (Spinner) findViewById(R.id.spinner1);
    spinner.setOnItemSelectedListener(this);
    loadSpinner();
}

private void loadSpinner() {
    Set<String> set = data.getAllData();


    List<String> list = new ArrayList<String>(set);

    adapter = new ArrayAdapter<String>(MainActivity.this,
            android.R.layout.simple_spinner_item, list);

    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

    spinner.setAdapter(adapter);
    spinner.setWillNotDraw(false);
}               


    @Override
    public void onItemSelected(AdapterView<?> parent, View view,
            int position, long id) {
        // TODO Auto-generated method stub          
    }


    @Override
    public void onNothingSelected(AdapterView<?> parent) {
        // TODO Auto-generated method stub          
    }


    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub          
    }
}

这是我的数据库管理器:

公共类 DBManager 扩展 SQLiteOpenHelper {

//Path to the device folder with databases
public static String DB_PATH;

//Database file name
public static String DB_NAME;
public SQLiteDatabase database;
public final Context context;
public final static int DB_VERSION = 6;

 public SQLiteDatabase getDb() {
    return database;
}

 public DBManager(Context context, String databaseName) {
    super(context, databaseName, null, DB_VERSION);
    this.context = context;
 //full path to the databases
 String packageName = context.getPackageName();
 DB_PATH = String.format("//data//data//%s//databases//", packageName);
 DB_NAME = databaseName;
 openDataBase();
}

 //This piece of code will create a database if it’s not yet created
public void createDataBase() {
    boolean dbExist = checkDataBase();
    if (!dbExist) {
        this.getReadableDatabase();
        try {
            copyDataBase();
        } catch (IOException e) {
            Log.e(this.getClass().toString(), "Copying error");
            throw new Error("Error copying database!");
        }
    } else {
        Log.i(this.getClass().toString(), "Database already exists");
    }
}


//Performing a database existence check
private boolean checkDataBase() {
    SQLiteDatabase checkDb = null;
    try {
        String path = DB_PATH + DB_NAME;
        checkDb = SQLiteDatabase.openDatabase(path, null,SQLiteDatabase.OPEN_READONLY);
    } catch (SQLException e) {
        Log.e(this.getClass().toString(), "Error while checking db");
    }
    //Android doesn’t like resource leaks, everything should 
    // be closed
    if (checkDb != null) {
        checkDb.close();
    }
    return checkDb != null;
}

//Method for copying the database
private void copyDataBase() throws IOException {
    //Open a stream for reading from our ready-made database
    //The stream source is located in the assets
    InputStream externalDbStream = context.getAssets().open(DB_NAME);

     //Path to the created empty database on your Android device
    String outFileName = DB_PATH + DB_NAME;

     //Now create a stream for writing the database byte by byte
    OutputStream localDbStream = new FileOutputStream(outFileName);

     //Copying the database
    byte[] buffer = new byte[1024];
    int bytesRead;
    while ((bytesRead = externalDbStream.read(buffer)) > 0) {
        localDbStream.write(buffer, 0, bytesRead);
    }
    //Don’t forget to close the streams
    localDbStream.close();
    externalDbStream.close();
}

public SQLiteDatabase openDataBase() throws SQLException {
    String path = DB_PATH + DB_NAME;
    if (database == null) {
        createDataBase();
        database = SQLiteDatabase.openDatabase(path, null,
            SQLiteDatabase.OPEN_READWRITE);
    }
    return database;
}

@Override
public synchronized void close() {
    if (database != null) {
        database.close();
    }
    super.close();
}
public Set<String> getAllData() {
      Set<String> set = new HashSet<String>();
      String selectQuery = "select * from cuisine";
      SQLiteDatabase db = this.getReadableDatabase();
      Cursor cursor = db.rawQuery(selectQuery, null);
      if (cursor.moveToFirst()) {
       do {
       set.add(cursor.getString(1));
       } while (cursor.moveToNext());
      }
      cursor.close();
      db.close();
      return set;
     }



@Override
public void onCreate(SQLiteDatabase db) {}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}




}

【问题讨论】:

  • "我在创建另外两个时遇到了问题" 您应该更详细地解释您遇到的问题。
  • 创建第一个,我使用 loadSpinner 中的 getAllData 填充它,在另外两个中,我是否再创建 2 个具有不同查询的 getAllData?我要创建另一个 loadSpinner 吗?我不知道如何继续@Takendarkk

标签: java android eclipse sqlite


【解决方案1】:

好的,首先你不应该从主线程查询你的数据库。

我建议使用 here 中描述的加载器。您可以拥有任意数量的加载器,在您的情况下,每个 Spinner 有 1 个(只需确保为它们提供不同的 ID)。

【讨论】:

    【解决方案2】:

    您需要清除传递给arrayadapter 的arraylist。因为当您使用第一个微调器时,您正在调用 gatAllData 并将该数据存储在 arraylist 中,并将其传递给 arrayadapter。下次对于第二个微调器,您将执行相同的过程,但它会连接到 arraylist 的先前条目。因此,在调用 getAllData 之前,您需要清除您的数组列表。它会解决你的问题。

    【讨论】: