使用setFilter QueryProvider重复列

时间:2013-12-01 21:42:12

标签: android sqlite listview simplecursoradapter

我有一个有问题的列表视图。我想用edittext实现经典搜索,我使用 addTextChangedListener TextWatcher()。 Listview从数据库中获取元素,因此我使用cursor和simplecursoradapter,因此我必须使用 setFilterQueryProvider 。当我在edittext中写一些东西时会出现问题,如果我写了一个产品的名称,它会更改列表中所有元素的名称。所以我不知道该怎么做。感谢帮助。

这是我的带有listview的java代码:

public class Lista_general extends ListActivity {

SimpleCursorAdapter adapter;
ListView list;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.lista_general);


     list = getListView();


    EditText edit =(EditText)findViewById(R.id.edit);


    // open database
    AdminSQLiteOpenHelper dbhelper = new AdminSQLiteOpenHelper(
            getBaseContext());
    SQLiteDatabase db = dbhelper.getReadableDatabase();

    // array for SimpleCursorAdapter
        String columns[] = new String[] { "PRODUCTO._id",  
       "nombre","category","CATEGORIAS._id","categoryid" };


    String orderBy = "category";


          // query database

       Cursor c = db.query("PRODUCTO, CATEGORIAS WHERE CATEGORIAS._id = categoryid  ", 
       columns,null,null, null, null, orderBy);


    c.moveToFirst();

    // array for SimpleCursorAdapter
    String from[] = new String[] { "nombre", "category", };
    //String from[] = new String[] { "nombre", "categoria", };

    int to[] = new int[] { R.id.name, R.id.cate, };

    // Adapter
    adapter = new SimpleCursorAdapter(getBaseContext(),
            R.layout.productos, c, from, to,
            SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);

    setListAdapter(adapter);


    list.setTextFilterEnabled(true);

    //Listener edit text
    edit.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence s, int start, int before,
                    int count) {

        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count,
                int after) {


        }

        @Override
        public void afterTextChanged(Editable s) {

            adapter.getFilter().filter(s.toString());  

        }
    });


    adapter.setFilterQueryProvider(new FilterQueryProvider() {

        @Override
        public Cursor runQuery(CharSequence constraint) {
            // TODO Auto-generated method stub

            AdminSQLiteOpenHelper dbhelper = new AdminSQLiteOpenHelper(
                    getBaseContext());
            SQLiteDatabase db = dbhelper.getReadableDatabase();


             Cursor mCursor = null;
              if (constraint == null  || constraint.length () == 0)  {


              mCursor = db.query("PRODUCTO, CATEGORIAS", new String[] { 
                      "PRODUCTO._id", "nombre","CATEGORIAS._id","category"}, 
              null, null, null, null, null);


              }
              else {



               mCursor = db.query(true,"PRODUCTO, CATEGORIAS", new String[] 
                      {"PRODUCTO._id", "nombre", "category","CATEGORIAS._id"}, 
              "nombre" + " like '%" + constraint + "%'", null,                      
                      null, null, null, null);
              }
              if (mCursor != null) {
               mCursor.moveToFirst();
              }



            return mCursor;
        }
    });
}

以下是我的错误视觉效果:

首先我的正常名单: http://i40.tinypic.com/2111k0p.png

我写完之后: http://i44.tinypic.com/23j04kg.png

1 个答案:

答案 0 :(得分:0)

FilterQueryProvider中生成的查询似乎未正确加入表格,因此您最终会得到PRODUCTOCATEGORIAS的所有可能组合(然后按PRODUCTO.nombre给人的印象是所有名字都已更改。

constraint直接插入查询中也存在潜在的安全风险,这为SQL注入攻击打开了大门。我不确定这在Android应用程序环境中有多严重,但在例如PHP Web应用程序中,这将允许任何人执行他们希望通过输入的任何 SQL精心设计的constraint


this question的答案看起来需要rawQuery()调用才能使用SQL JOIN,因此我会按以下方式更改您的查询...

对于没有过滤器的查询(例如onCreate();以及runQuery()没有constraint):

cursor = db.rawQuery("SELECT PRODUCTO._id, nombre, category, CATEGORIAS._id FROM PRODUCTO INNER JOIN CATEGORIAS ON PRODUCTO.categoryid = CATEGORIAS._id", null);

使用过滤器查询

String[] params = { constraint.toString() };
cursor = db.rawQuery("SELECT PRODUCTO._id, nombre, category, CATEGORIAS._id FROM PRODUCTO INNER JOIN CATEGORIAS ON PRODUCTO.categoryid = CATEGORIAS._id WHERE nombre LIKE ('%' || ? || '%')", params);