Android 使用setFilterQueryProvider重新重复列
我有一个列表视图有问题。我想用edittext实现经典搜索,我正在使用addTextChangedListener和TextWatcher()。Listview从数据库获取元素,因此我使用游标和simplecursoradapter,因此我必须使用setFilterQueryProvider。当我在编辑文本中写东西时,问题就出现了,如果我写产品的名称,它会改变列表中所有元素的名称,所以我不知道该怎么办。谢谢你的帮助 以下是我在listview中的java代码:Android 使用setFilterQueryProvider重新重复列,android,sqlite,listview,simplecursoradapter,Android,Sqlite,Listview,Simplecursoradapter,我有一个列表视图有问题。我想用edittext实现经典搜索,我正在使用addTextChangedListener和TextWatcher()。Listview从数据库获取元素,因此我使用游标和simplecursoradapter,因此我必须使用setFilterQueryProvider。当我在编辑文本中写东西时,问题就出现了,如果我写产品的名称,它会改变列表中所有元素的名称,所以我不知道该怎么办。谢谢你的帮助 以下是我在listview中的java代码: public class List
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;
}
});
}
以下是我的错误的视觉效果:
首先,我的正常列表:
在我写完之后:
在
FilterQueryProvider
中生成的查询似乎没有正确地连接表,因此您最终得到了PRODUCTO
和CATEGORIAS
的所有可能组合(然后通过PRODUCTO.nombre
进行过滤,以给人留下所有名称都已更改的印象)
直接在查询中插入约束也存在潜在的安全风险,这为SQL注入攻击打开了大门。我不确定这在Android应用程序的上下文中有多严重,但在例如PHP web应用程序中,这将允许任何人通过输入精心编制的约束来执行他们想要的任何SQL
从对它的回答来看,使用SQLJOIN
需要调用rawQuery()
,因此我将更改您的查询如下
对于无过滤器的查询(即在onCreate()
中;以及在runQuery()
中没有约束的情况下):
对于使用筛选器进行查询:
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);
非常感谢你,这就是答案。只有少量的校正字符串[]params={(字符串)约束};我正在使用eclipse,它说我必须向字符串添加cast。好的一点是,整个CharSequence
的事情一直让我感到困惑。使用constraint.toString()
而不是强制转换更安全,我将编辑答案。
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);