I'm trying to remove a couple of rows in a sqlite database programmatically for android and am wondering what the whereArgs are referring to in this documentation:
http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#delete(java.lang.String,%20java.lang.String,%20java.lang.String[])
Can someone give me an example?
whereArgs are the values to the where clause. When you use the "?" (placeholder) in the second argument (whereClause), you've to provide the whereArgs. See this post for details.
Put "=?" on the end of the second argument (whereClause), like this:
delete(CONTENT_URI, TEXT + "=?", new String [] { text } );
The number of ? is the number of arguments.
Placeholders ? don't work (buggy) - so you need to construct the whereClause (selection) and send null arguments (selectionArgs)
e.g. To load a dynamic list from using user search text:
mCustomerMenuList = (ListView)findViewById(R.id.customer_menu_list);
mSearchText = (EditText)findViewById(R.id.autoCompleteTextView1);
mSearchText.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable t) {
//Reload the query using the search text
ManageMyCustomerMenuList();
mCustomerMenuList.setAdapter(mAdapter);
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// Auto-generated method stub
}
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// Auto-generated method stub
}
});
and in your ManageMyCustomerMenuList() query code place something like:
String s = mSearchText.getText().toString().toLowerCase();
String whereClause = Browser.BookmarkColumns.TITLE+" LIKE ?";
String whereArgs [] = new String[] {"%" +s+"%"};
mCustomerCursor = managedQuery(android.provider.Browser.BOOKMARKS_URI,
new String[] {
Browser.BookmarkColumns._ID,
Browser.BookmarkColumns.TITLE,
Browser.BookmarkColumns.URL
}, whereClause, whereArgs, mSqlLimit
);
mAdapter = new SimpleCursorAdapter(this, R.layout.row_layout_test,
mCustomerCursor, new String[] {
Browser.BookmarkColumns.TITLE,
Browser.BookmarkColumns.URL
}, new int[] {
R.id.test_layout_view1,
R.id.test_layout_view2
}
);
Related
I am using a AutoCompleteTextView (will later be changing this to an editText but one problem at a time) to filter the results of my listView implementing a textWatcher:
fqp = new FilterQueryProvider() {
#Override
public Cursor runQuery(CharSequence constraint) {
String itemName = constraint.toString();
return getSearch(itemName);
}
};
Cursor getSearch(String itemName) {
String searchSelect = "(" + MediaStore.Audio.Media.TITLE + " LIKE ? )";
String[] selectArgs = { "%" + itemName + "%"};
Cursor searchCursor = getContentResolver().query(
queryUri,
projection,
searchSelect,
selectArgs,
MediaStore.Audio.Media.TITLE + " ASC"
);
return searchCursor;
}
public void onTextChanged(CharSequence s, int start, int before,
int count) {
String empty = "";
if(s.toString() == empty){
adapter.changeCursor(getAll());
adapter.notifyDataSetChanged();
}else{
adapter.getFilter().filter(s.toString());
adapter.notifyDataSetChanged();
}
}
This filter works just fine, but i need to figure out a way to reset my list once my autoCompleteTextView is empty. Surely there is a correct way to do this other than testing if it's empty but that's what i tried to no avail. Also should i just create two Cursors: one containing my full list and the other my filtered list so i don't have to re-query the content provider?
The issue seems to lie in this line
if(s.toString() == empty)
In Java, you cannot compare Strings like this, you need to use
if(s.toString().equals(empty))
Also TextWatcher is not getting called because the listener is not linked to your AutoCompleteTextView.
Also should i just create two Cursors: one containing my full list and the other my filtered list so i don't have to re-query the content provider?
If the filtered list will have the same data every time, then yes it's better to keep a reference to it instead of doing a new query.
Example using EditText:
adapter.setFilterQueryProvider(fqp);
search.addTextChangedListener(watch);
fqp = new FilterQueryProvider() {
#Override
public Cursor runQuery(CharSequence constraint) {
String itemName = constraint.toString();
return getSearch(itemName);
}
};
Cursor cursor = getContentResolver().query(
queryUri,
projection,
null,
null,
MediaStore.Audio.Media.TITLE+" ASC"
);
Cursor getSearch(String itemName) {
String searchSelect = "(" + MediaStore.Audio.Media.TITLE + " LIKE ? )";
String[] selectArgs = { "%" + itemName + "%"};
Cursor searchCursor = getContentResolver().query(
queryUri,
projection,
searchSelect,
selectArgs,
MediaStore.Audio.Media.TITLE + " ASC"
);
return searchCursor;
}
TextWatcher watch = new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
String empty = "";
if (s.toString().equals(empty)) {
adapter.changeCursor(cursor);
adapter.notifyDataSetChanged();
} else {
adapter.getFilter().filter(s.toString());
adapter.notifyDataSetChanged();
}
}
#Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
};
I have a listview with a problem. I want to implement the classic search with the edittext, i am using the addTextChangedListener with TextWatcher(). The Listview gets the elements from a database so I use cursor and simplecursoradapter so i have to use the setFilterQueryProvider. The problem appears when I write something in the edittext, if I write the name of a product it changes all the names of the elements in the list.So i dont know what to do. Appreciate the help.
here is my java code with the listview:
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;
}
});
}
Here is a visual of my error:
first my normal list:
http://i40.tinypic.com/2111k0p.png
after I wrote:
http://i44.tinypic.com/23j04kg.png
It looks like the queries generated in the FilterQueryProvider are not joining the tables properly, so that you end up with every possible combination of PRODUCTO and CATEGORIAS (which are then filtered by PRODUCTO.nombre to give the impression that all the names have changed).
There's also a potential security risk with inserting constraint directly into the query, this opens the door to SQL injection attacks. I'm not sure how serious this is in the context of Android apps, but in for example a PHP web application this would allow anyone to execute any SQL they wished by entering a carefully crafted constraint.
From the answers to this question it looks like a rawQuery() call is needed in order to use SQL JOIN so I would change your queries as follows...
For querying with no filter (i.e. in onCreate(); and in runQuery() where there is no constraint):
cursor = db.rawQuery("SELECT PRODUCTO._id, nombre, category, CATEGORIAS._id FROM PRODUCTO INNER JOIN CATEGORIAS ON PRODUCTO.categoryid = CATEGORIAS._id", null);
For querying with a filter:
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);
Folks.
I've designed a currency exchange application in which i got all exchange rates once at application start and create own SQLite DB then easily pull them into the converter interface. I've designed the change to be done in my Edittext onTextChanged listener with a textwatcher and all works perfectly. I've also have a listview in the same activity for Favorite exchange rates and its also has to be calculated every time the edittext changes. My main problem is that I've got a slow performance and freeze issues in my application. I've tried to implement Asynctask to process the calculations but it didn't help me and i still get the performance issues. Hereunder my code for your reference. Please Advice !!
Text Watcher :
valval.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before,
int count) {
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void afterTextChanged(final Editable s)
{
Calculate();
}
});
Calculate :
private void Calculate()
{
curs = mDb.query(MyDbHelper.TABLE_NAME, columns, MyDbHelper.COL_Common
+ "=" + "?", new String[] { From[xxxto] + From[xxxfrom] },
null, null, null);
cursD = mDb.query(MyDbHelper.TABLE_NAME, columns, MyDbHelper.COL_Common
+ "=" + "?", new String[] { From[xxxfrom] + From[xxxto] },
null, null, null);
curs.moveToFirst();
cursD.moveToFirst();
double selection = curs.getDouble(curs
.getColumnIndex(MyDbHelper.COL_Currone));
double selection2 = cursD.getDouble(cursD
.getColumnIndex(MyDbHelper.COL_Currone));
Long myNum = Long.parseLong(valval.getText().toString().trim());
double myNum3 = Double.parseDouble(new DecimalFormat("#.######").format(myNum * selection2));
valval2.setText(String.valueOf(myNum3));
Cursor B = mDb.query(MyDbHelper.TABLE_NAME, columns,
MyDbHelper.COL_CurrFavor + " LIKE ? And "
+ MyDbHelper.COL_Currsecond + " LIKE ?", new String[] {
"YES", "EUR" }, null, null, null);
for (int s = 0; s < B.getCount() - 1; s++)
{
B.moveToPosition(s);
String ZVZV = B.getString(0);
int BSBS = B.getInt(9);
Cursor curcur = mDb.query(MyDbHelper.TABLE_NAME, columns, MyDbHelper.COL_Common
+ "=" + "?", new String[] { From[xxxfrom] + From[BSBS-1] },
null, null, null);
curcur.moveToFirst();
double calcal = curcur.getDouble(6);
ContentValues args = new ContentValues();
double formattedNumber = Double.parseDouble(new DecimalFormat("#.######").format(myNum * calcal));
args.put(MyDbHelper.COL_Currsum,formattedNumber );
mDb.update(MyDbHelper.TABLE_NAME, args, "_id =" + ZVZV, null);
}
cursm.requery();
}
What I can imagine of from your description is, you're most likely having 2 EditTexts, where user only input to first, and you will sync the converted value for second, is this true? If it is, may I suggest you not to perform the operation right after every text change?
You may want to do Calculate() only after user finishes his input, perhaps one second delay of calculation is acceptable?
// Declare these as class variable
private Handler handler = new Handler();
private Runnable calculateRunnable = new Runnable() {
public void run() {
Calculate();
}
}
As for your TextWatcher, change this
public void afterTextChanged(final Editable s) {
handler.removeCallbacks(calculateRunnable);
handler.postDelayed(calculateRunnable, 1000);
}
I want to ask a little question. I want to know which is the best way I can filter my list view which I am populating from sqlite database and I want to filter it depending on users entered letters in edit text. I'm not showing any code because I have only sqlite statements and that's it. I have to change the sqlite statement which I'm using to populate the database.
So my question is, how can I change my sqlite statement when user entered letters in edit text, and how can I update my listview with the new data filtered with the new sql statement.
I had the same issue and solved it as follows:
//Search text and changed handler
EditText tbSearch = (EditText)findViewById(R.id.android_searchbox);
tbSearch.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void afterTextChanged(Editable s) {
ListView av = getListView();
SimpleCursorAdapter filterAdapter = (SimpleCursorAdapter)av.getAdapter();
filterAdapter.getFilter().filter(s.toString());
}
});
entries.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
return mDbHelper.fetchAllEntries(constraint);
}
});
With this approach you will need a method similar to FetchAllEntries(string sFilter)
/*
* Override to return a Cursor over the list of Entries filtered by a
* constraint
*
* #return Cursor over filtered Entries
*/
public Cursor fetchAllEntries(CharSequence constraint) {
if (constraint == null || constraint.length() == 0) {
// Return the full list
return fetchAllEntries();
} else {
String value = "%" + constraint.toString() + "%";
String[] columns = new String[] { KEY_ROWID, KEY_TITLE,
KEY_BODY, KEY_USER_PROFICIENCY };
return mDb.query(DATABASE_TABLE, columns,
KEY_TITLE + " like ? OR " + KEY_BODY + " like ? ", new String[] { value, value }, null, null,
KEY_TITLE + " ASC ");
}
}
Here I have a table with two columns (title, body)
Check the answer to your previous question, they are very similar : search bar
I have a table in a database and I would like to show only one row of this table. The table has 3 fields (ID, Title and Description).
I want to filter the rows depending on the Title.
I have this code:
Cursor cursor = db.query(TABLE_NAME, FROM, null, null, null, null, ORDER_BY);
where the third field is the selection one (a String). But I don't know what I have to put exactly to select only the row that I want to show. Thanks
String[] FROM = { // ID of the column(s) you want to get in the cursor
ID,
Title,
Description
};
String where = "Title=?"; // the condition for the row(s) you want returned.
String[] whereArgs = new String[] { // The value of the column specified above for the rows to be included in the response
"0"
};
return db.query(TABLE_NAME, FROM, where, whereArgs, null, null, null);
This should give you a cursor with all your columns but only containing the rows where the value of the Title column is equal to 0.
try this
Cursor cursor = db.query("TABLE_NAME",new String[]{"ColumnName"}, "ColumnName=?",new String[]{"value"}, null, null, null);
You can search by following code in SQLite;
In MainActivity;
search.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
adapter.getFilter().filter(s.toString());
}
});
adapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
return
//Here you can filter data by any row , just change text replace of "subject"
dbManager.fetchdatabyfilter(constraint.toString(),"subject");
}
});
DatabaseHelper.java
public Cursor fetchdatabyfilter(String inputText,String filtercolumn) throws SQLException {
Cursor row = null;
String query = "SELECT * FROM "+DatabaseHelper.TABLE_NAME;
if (inputText == null || inputText.length () == 0) {
row = database.rawQuery(query, null);
}else {
query = "SELECT * FROM "+DatabaseHelper.TABLE_NAME+" WHERE "+filtercolumn+" like '%"+inputText+"%'";
row = database.rawQuery(query, null);
}
if (row != null) {
row.moveToFirst();
}
return row;
}