I’ve been searching the web for a few day’s (actually nights ;), but at the moment I’m very stuck in finding a solution for my problem. Basically what I want is a listview of SQLite, with filter and the important thing: keeping the list-row result consistent with the SQLite row’s.
I’ve started easy with a basic listview, but it wasn’t possible to keep consistency between the SQLite row’s and the filtered listview.
Then I moved on to a simplecursor, but I never get a filtered result, only the complete SQLite list is being showed.
I think I’m missing something in the direction of telling the SimpleCursorAdapter to refresh with the filtering. I’ve found a lot of pages with some pieces of code, but can’t seem to implement it in my own code. It has to do with: setFilterQueryProvider ( I think)
Also I’ve read this SimpleCursorAdapter is now obsolete and moves to loaders?
Let me get this one step at a time, so hopefully with a bit of help I can get this filtering to work an move on to loaders.
Thank you for taking the time and read my code. As it’s now almost 5 o clock in the morning, I hope my English is still okay 🙂
public class MainActivity extends Activity {
String TAG = "MainActivity"; // for logging purposes
private ArrayList<String> data; // location which receives all products to display in the list
static int ProductCursorPosition; // the id which will returned by pressing the listview
private ListView listView_Products; // define the listview variabele
SimpleCursorAdapter adapter;
EditText inputSearch;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.act_main);
Log.v(TAG, "onCreate");
// Worker dbworker = new Worker(this.getApplicationContext());
// Log.v(TAG,"Open database");
// dbworker.open();
// Log.v(TAG,"Get database entry's");
// data = dbworker.getProductListView();
// dbworker.close();
}
@Override
protected void onResume() {
super.onResume();
Log.v(TAG, "onResume");
displayListView(); // show me the products in the listview
aantalbestellingen(); // update the total numbers of bread waiting in order
}
// display the listview with products
public void displayListView() {
Log.v(TAG,"Select database");
Worker dbworker = new Worker(this.getApplicationContext());
Log.v(TAG,"Open database");
dbworker.open();
String[] columns = new String[]{ Worker.KEY_ROWID, Worker.KEY_PRODUCT};
String[] from = new String[]{Worker.KEY_PRODUCT};
int [] to = {R.id.text1};
final Cursor cursor = Worker.ourDatabase.query(true, // isdistinct
Worker.DB_TABLE_PROD, // table name
columns,// select clause
null, // where cluase
null, // where clause parameters
null, // group by
null, // having
null, // nogwat
null);// limit
startManagingCursor(cursor);
adapter = new SimpleCursorAdapter(this, R.layout.lv_customlayout01, cursor, from, to);
// find the view for the listview and connect the listView_Products to it
listView_Products = (ListView) findViewById(R.id.lvProducts);
// Shows the adapter content in the listview
listView_Products.setAdapter(adapter);
dbworker.close();
/**
* Enabling Search Filter
* */
inputSearch = (EditText) findViewById(R.id.etSearchbar);
inputSearch.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
// When user changed the Text
Log.v(TAG,"Filter: onTextChanged");
Log.v(TAG,"Filterstring: " + cs);
Log.v(TAG,"adapter: " + adapter);
adapter.getFilter().filter(cs);
// adapter.getFilter().filter(cs.toString());
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
Log.v(TAG,"Filter: beforeTextChanged");
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
Log.v(TAG,"Filter: afterTextChanged");
// adapter.notifyDataSetChanged();
}
});
listView_Products.setOnItemClickListener( new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// TODO Auto-generated method stub
Log.v(TAG, "Pressed the listview\n" +
"View arg2 = " + arg2 + "\n" +
"int arg3 = " + arg3 + "\n");
}
});
}
}
Ok, I’ve changed the code a bit:
Now I’m having a listview with filter results.
// display the listview with products
public void displayListView() {
Log.v(TAG,"DB select");
Worker dbworker = new Worker(this.getApplicationContext());
Log.v(TAG,"DB open");
dbworker.open();
// SQLite get cursor from Worker
final Cursor ItemCursor = Worker.cursorsetup01();
// Start managing the cursor
startManagingCursor(ItemCursor);
// Columns to be bound to the adapter
String[] FROMcolumns = new String[]{Worker.KEY_PRODUCT, Worker.KEY_INFO };
// THE XML DEFINED VIEWS WHICH THE DATA WILL BE BOUND TO
int[] ToXMLView = new int[] {R.id.tvProduct, R.id.tvProductInfo};
// CREATE THE ADAPTER USING THE CURSOR POINTING TO THE DESIRED DATA AS WELL AS THE LAYOUT INFORMATION
Log.v(TAG,"CREATE THE ADAPTER");
adapter = new SimpleCursorAdapter(this, R.layout.lv_customlayout01, ItemCursor, FROMcolumns, ToXMLView);
// find the view for the listview and connect the listView_Products to it
listView_Products = (ListView) findViewById(R.id.lvProducts);
// SET THIS ADAPTER AS YOUR LISTACTIVITY'S ADAPTER
listView_Products.setAdapter(adapter);
adapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(final CharSequence substring) {
String[] dbquerycolumns = new String[]{Worker.KEY_PRODUCT, Worker.KEY_INFO, Worker.KEY_ROWID };
Worker dbworker = new Worker(getApplicationContext());
Log.v(TAG,"Open database");
dbworker.open();
return Worker.ourDatabase.query(
Worker.DB_TABLE_PROD, // TABLE
dbquerycolumns,// COLUMNS
"product LIKE '%" + substring.toString() + "%'" , // SELECTION
null, // SELECTION ARGS
null, // GROUP BY
null, // HAVING
"_id LIMIT 100");// ORDER BY (limit the results to 100)
}
});
// Connect the textedit searchbar to a change listener and action upon changes
mySearchText = (EditText)findViewById (R.id.etSearchbar);
mySearchText.addTextChangedListener (new TextWatcher() {
@Override
public void afterTextChanged (Editable s) {
Log.v(TAG,"Textchanged: AfterTextChanged: " + s);
adapter.getFilter().filter(s.toString());
startManagingCursor(ItemCursor);
}
Couple of things that would help you
Now, couple of things that you would have to amend to your existing code.
Collection1Collection2Collection2and recreate it using the new filter (b) create a new instance of the Adapter with the latest collection2 (c) set this new instance to the listView (d) recycle the old instance for optimizationThis, way your updates will be instantaneous to the user, while you would have the full control in resolving your current issues as well as any that might come.