Using CursorLoader to query SQLite DB and populate AutoCompleteTextView

前端 未结 3 1798
我在风中等你
我在风中等你 2021-02-13 03:42

I have a SQLite database I would like to query. I want to target Android 2.2 through ICS. I came across this article on how to do this, but it uses deprecated code (does not que

相关标签:
3条回答
  • 2021-02-13 04:28

    I created a SQLiteHelper class. Im my case, I have an sqlite database that I copy from assets folder to the /data/data directory if not there:

    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);
    }
    

    To fill the auto Autocomplete TextView on my activity:

    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();
    

    Populate method:

    //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;
    }
    

    Then I set it:

    // 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;
            }
        });
    

    Hope you understand. I can't give you my full source because this is in a marketplace app I developed. You can check it out before trying to do all the work: https://play.google.com/store/apps/details?id=com.life.plus.studios.bartender.drink.recipes.light

    0 讨论(0)
  • 2021-02-13 04:29

    I know this is an old question but for people who visit this page:

    SimpleCursorAdapter has a new constructor:

    SimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags)
    

    this cunstructor does not use UI thread. You can use it safey.

    0 讨论(0)
  • 2021-02-13 04:48

    I do not have the code on hand, but I asked a similar question before:

    Android db loading chat for chat application

    If you read it carefully, you can figure out how to use a CursorLoader for your sqlite database ;)

    0 讨论(0)
提交回复
热议问题