Utilizar CursorLoader para consultar la base de datos SQLite y rellenar AutoCompleteTextView
Tengo una base de datos SQLite que me gustaría consultar. Quiero apuntar a Android 2.2 a través de ICS. Me encontré con este artículo sobre cómo hacer esto, pero utiliza código obsoleto (no consulta asincrónicamente, pero en el subproceso de interfaz de usuario). Desde entonces he leído que puedo usar CursorLoader
junto con LoaderManager
para hacer esta tarea la forma preferida, las mejores prácticas (como para no atascar el hilo de la interfaz de usuario).
El problema es encontrar un ejemplo conciso para explicarme cómo hacerlo. 1) cargar la base de datos, 2) consultarla, 3) utilizar el resultado para rellenar una vista de lista AutoCompletetextBox.
- La base de datos Sqlite onUpgrade () no se llama
- ¿Tengo que usar _ID como una clave primaria de SQlite? Y tiene que ser un INT? (Android Dev)
- Android JUnit4 Pruebas - ¿Dónde obtener el contexto de?
- Android SQLiteOpenHelper - clase diferente para cada tabla?
- Cómo ocultar filas específicas de un cursor en android
¿Existe tal ejemplo?
- Seleccione la última fila
- Excepción aleatoria android.database.sqlite.SQLiteException: no se puede abrir el archivo de base de datos
- AUTOINCREMENT sólo está permitido en un INTEGER PRIMARY KEY - android
- Devolver datos de AsyncTask Android
- Android, Diacritic Insensitive SQLite Búsqueda
- por qué c.moveToFirst () no saltará la primera fila
- Cómo utilizar TRIGGER en Android SQLite
- Uso de ORM de azúcar con UUID o Joda-Time
Sé que esta es una vieja pregunta, pero para las personas que visitan esta página:
SimpleCursorAdapter tiene un nuevo constructor:
SimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags)
este cunstructor no utiliza hilo UI. Puedes usarlo safey.
Creé una clase SQLiteHelper. Im mi caso, tengo una base de datos de sqlite que copio de la carpeta de los activos al directorio / data / data si no allí:
private DatabaseHelper(Context context, String name, CursorFactory factory, int version) { super(context, DB_NAME, null, 1); this.mContext = context; } // getInstance() singleton public static synchronized DatabaseHelper getInstance(Context context) { if (_instance == null) { _instance = new DatabaseHelper(context,null,null,1); } return _instance; } @Override public void onCreate(SQLiteDatabase db) { // Leave it blank, we don't want to create. } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // Leave it blank, we don't want to upgrade } public void createDataBase() throws IOException{ boolean dbExist = checkDataBase(); if(dbExist){ openDataBase(); // check the version number; SQLiteCursor cursor = runQuery("select versionNumber from version where VersionType = \"CURRENT\""); if (cursor!=null){ cursor.moveToFirst(); int version = cursor.getInt(cursor.getColumnIndex("versionNumber")); if (version!=SQL_VERSION){ //TODO - grab the favorites and ingredients first. ArrayList<String> favorites = getFavorites(); // I think I need to close the db before erasing it, then open new one. close(); mContext.deleteDatabase(DB_NAME); this.getReadableDatabase(); copyDataBase(); openDataBase(); for (int i = 0; i<favorites.size();i++){ insert(Constants.TABLE_FAVORITES,Constants.FAVORITE,favorites.get(i)); } close(); } } }else{ //By calling this method and empty database will be created into the default system path //of your application so we are gonna be able to overwrite that database with our database. this.getReadableDatabase(); copyDataBase(); } } private void copyDataBase(){ //Open your local db as the input stream InputStream myInput; try { myInput = mContext.getAssets().open(DB_NAME); // Path to the just created empty db String outFileName = LOCATION + DB_NAME; //Open the empty db as the output stream OutputStream myOutput = new FileOutputStream(outFileName); //transfer bytes from the inputfile to the outputfile byte[] buffer = new byte[1024]; int length; while ((length = myInput.read(buffer))>0){ myOutput.write(buffer, 0, length); } //Close the streams myOutput.flush(); myOutput.close(); myInput.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void openDataBase() throws SQLException{ //Open the database String myPath = LOCATION + DB_NAME; mDatabase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE); } @Override public synchronized void close() { if(mDatabase != null) mDatabase.close(); super.close(); } public SQLiteCursor runQuery(String query){ return (SQLiteCursor) mDatabase.rawQuery(query,null); } private boolean checkDataBase(){ SQLiteDatabase checkDB = null; try{ String myPath = LOCATION + DB_NAME; checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY); }catch(SQLiteException e){ //database does't exist yet. } if(checkDB != null){ checkDB.close(); } return checkDB != null ? true : false; } // all insert does is insert to favorites and into your bar. public void insert(String table, String column, String value) { ContentValues values = new ContentValues(); values.put(column, value); mDatabase.insert(table, null, values); } public void delete(String table, String column, String value){ mDatabase.delete(table,column+" = \""+value+"\"",null); }
Para rellenar el Auto Autocompletar TextView en mi actividad:
startManagingCursor(mCursor); // get instance of database helper class mDatabaseHelper = DatabaseHelper.getInstance(this); // create database for first time try { mDatabaseHelper.createDataBase(); } catch (IOException e) { //Log.i(TAG,"Could not create the database"); e.printStackTrace(); } // open the database mDatabaseHelper.openDataBase(); mDrinks = this.populate();
Método Populate:
//populates by drinks private ArrayList<String> populate() { ArrayList<String> items = new ArrayList<String>(); mCursor = mDatabaseHelper.runQuery( "select "+ Constants.TITLE +" from " +Constants.TABLE_DRINK+" order by " +Constants.TITLE); if (mCursor != null){ mCursor.moveToFirst(); while (!mCursor.isAfterLast()){ items.add(mCursor.getString(mCursor.getColumnIndex(Constants.TITLE))); mCursor.moveToNext(); } } return items; }
Entonces lo puse:
// when text changes, autocomplete happens mSearchTextView = (AutoCompleteTextView) findViewById(R.id.search_drink); mSearchTextView.setAdapter( new ArrayAdapter<String>( this, R.layout.list_item, mDrinks)); mSearchTextView.setClickable(true); // clear the text when the searchTextView is clicked. Necessary for // clearing after pressing enter in an invalid drink. mSearchTextView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mSearchTextView.setText(""); } }); mSearchTextView.setOnItemClickListener(new OnItemClickListener(){ @Override public void onItemClick(AdapterView<?> parent, View view, int position, long arg3) { // TODO - here we need to get the name, then search for ingredients and show everything in // an alert dialog. Here is main logic. buildDialog(parent.getItemAtPosition(position).toString()); } }); mSearchTextView.setOnEditorActionListener(new OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (event != null&& (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) { InputMethodManager in = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); in.hideSoftInputFromWindow(mSearchTextView .getApplicationWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); Toast.makeText(v.getContext(), "Please Select a Drink from the Auto Complete or the List Shown", Toast.LENGTH_LONG).show(); } return false; } });
Espero que entiendas. No puedo darte mi fuente completa porque se trata de una aplicación de mercado que desarrollé. Puede comprobarlo antes de intentar realizar todo el trabajo: https://play.google.com/store/apps/details?id=com.life.plus.studios.bartender.drink.recipes.light
No tengo el código a mano, pero hice una pregunta similar antes:
Android db cargando chat para aplicaciones de chat
Si lo lee con cuidado, puede averiguar cómo usar un CursorLoader para su base de datos sqlite;)
- Rendimiento Android alcanzado en versiones posteriores a 2.3.5 (phonegap / cordova)
- android-Cómo ejecutar el servicio en diferentes hilos de rosca principal?