我有一个有问题的列表视图。我想用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答案 0 :(得分:0)
FilterQueryProvider
中生成的查询似乎未正确加入表格,因此您最终会得到PRODUCTO
和CATEGORIAS
的所有可能组合(然后按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);