Refresh spinner data - android

I have an application with a Spinner whos data is populated by a cursor from the database. Works great if there is something in the database table on startup. However, if I add something to the database after the app is running my spinner always shows that it has zero choices, even if one was there to begin with.
My code is as follows. The adapter.getCursor().requery(); did no good. I would like the Spinner to update its choices when the user clicks on it and I found a couple posts on StackOverflow that say you have to use the TextView behind the Spinner for the OnClickListener. However, for me that did nothing. Mostly likely because I'm missing one minor
c1 = myDbHelper.readCars();
startManagingCursor(c1);
// create an array to specify which fields we want to display
String[] from = new String[]{"nickname"};
// create an array of the display item we want to bind our data to
int[] to = new int[]{android.R.id.text1};
adapter = new SimpleCursorAdapter(this, android.R.layout.simple_spinner_item, c1, from, to);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinVehicle.setAdapter(adapter);
txtVehiclePrompt.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
adapter.getCursor().requery();
}
});

Just change the underlying data and call notifyDataSetChanged()
list.clear();
//list modify
list.add("A");
list.add("B");
dataAdapter.notifyDataSetChanged();

Ok,
I got it figured out. I needed to close the adapter, stop managing the cursor, close the cursor & close the db helper in the onSuspend() method then set everything back up in the onResume method since I was using a seperate activity to add records to the table.

Related

Android AsyncTask for Custom ListView

In my Android application I am having custom ListView that contains EditText and Spinner.
My problem is when I choose a Spinner (spDevice) I need to load corresponding values in another spinner (spModel). The problem I am facing is, when I select the value in spDevice its loading corresponding values in the spModel after some time delay, its not loading immediately (sometime data is not loading properly). I feel we have to use AsyncTask for this. Can anyone help me how to create AsyncTaskfor this or else can anyone tell me whats the best method to solve this issue.
Below is the code I am using now
private void spDevicesetItemSelectedListener(final DeviceHolder holder){
holder.spDevice.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int position,long id) {
String strDevices =(String)parent.getSelectedItem(); //Get selected value from SpDevices
ArrayList<String> lstModels = db.getAllModels(strDevices);
// Creating adapter for spinner
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(context,android.R.layout.simple_spinner_item, lstModels);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// attaching data adapter to spinner
holder.spModel.setAdapter(dataAdapter);
Its not needed, basically AsyncTask are used for long running tasks like network operations, database operations. One thing remind 'AsyncTask' are not needed for faster operations. The delay its taking is to fetch data from database, so using AsyncTask, it will not fasten up the loading.
I had solved this issue through calling AsyncTask, its working perfectly as intended. I feel in Custom ListView with more than one Spinner and the values are dependent on other Spinner, this is the best way to do. If I am wrong means correct me
if(strDevices != null && ! strDevices.isEmpty()) {
try {
ArrayList<String> lstModels = new LongOperation().execute(strDevices).get(); // Call Async Task
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(context, android.R.layout.simple_spinner_item, lstModels);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// attaching data adapter to spinner
holder .spModel.setAdapter(dataAdapter);
} catch (Exception e){
e.printStackTrace();;
}
}

ListView does not show changes until focus changes after notifyDataSetChanged

I have an AlertDialog with a ListView set to multiple selection on it. It also has a Button on it.
The Button open another AlertDialog that if ok'ed will remove the selected items from the data set of the ListView, and then tell the adapter of the list view that the dataset has changed with the notifyDataSetChanged() method.
This all works fine except for one thing. The ListView does not update it's content until I interact with something. Then it updates to the correct data.
This is not a big problem, but I really would like the ListView to appear correct at once, and not just after the focus has changed.
Code:
Button remove = (Button) view.findViewById(R.id.btn_remove_questions_edit_rack);
final Context con = this;
remove.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
Builder warnBuild = new Builder(con);
warnBuild.setMessage(R.string.question_deletion_warning);
warnBuild.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
SparseBooleanArray checked = list.getCheckedItemPositions();
for (String s : keys)
{
int i = keys.indexOf(s);
if (checked.get(i))
{
toRemove.add(map.get(s));
map.remove(s);
}
}
keys.clear();
keys.addAll(map.keySet());
((ArrayAdapter) list.getAdapter()).notifyDataSetChanged();
list.clearChoices(); //This makes sure the selection is cleared, if it isn't, some of the other items (those that now has the index of the selected items) will be selected when the View refreshes.
dialog.dismiss();
}
});
//Negative button here, not relevant.
}
});
Where map and keys are:
final HashMap<String, QualityQuestion> map = new HashMap<>();
//I add items to the map
final ArrayList<String> keys = new ArrayList<>(map.keySet());
And toRemove is where I store the items to be removed from the actual object they are on when the ok button on the original AlertDialog is pressed.
This is how I populate my ListView in the first place:
final ListView list = (ListView) view.findViewById(R.id.list_questions_edit_rack);
list.setAdapter(
new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_activated_1,
keys));
I have tried things like list.invalidateViews(), list.invalidate and other things I found in questions similar to mine here on SO. But none of that made any difference. I suspect my problem to be different from theirs since my items clearly are updated, it just takes a change of focus on the original AlertDialog for the change to be visible.
How can I make the ListView show the changes in it's data source imidiatly insted of after a focus change?
By calling
((ArrayAdapter) list.getAdapter()).notifyDataSetChanged();
you get a fresh adapter which is almost certainly not identical to the anonymous adapter you used to populate your list in the first instance.
See also the documentation for ListView.getAdapter()
Returns the adapter currently in use in this ListView.
The returned adapter might not be the same adapter passed to setAdapter(ListAdapter) but might be a WrapperListAdapter.
From the point of view of this fresh adapter, the data set hasn't changed because the changes happened way before it was instantiated.
To solve your problem, make your list and your list adapter members of your activity class (or the scope where you want to keep them alive):
private ArrayList<String> keys;
private ArrayAdapter myAdapter;
private ListView list;
Then in your "onCreate()"
keys = ...; // initialization of ArrayList with the needed data
myAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_activated_1,
keys);
list = (ListView) view.findViewById(R.id.list_questions_edit_rack);
list.setAdapter(myAdapter);
This way, in your "OnClickListener" you can notify "myAdapter":
keys.addAll(map.keySet());
myAdapter.notifyDataSetChanged();
Hope this helps :)
You can tweak it, by granting focus to another view, and then requesting it back:
view.requestFocus();
You can also use:
view.requestFocusFromTouch();

Populating an Android Spinner from an SQLite but with two fields?

I've finally managed to populate a spinner from an sqlite db after much messing about with this code however it's only using one field and I want First and Last names on the same spinner item?
The code is as follows:
private void fillSpinner() {
Cursor c = myDbHelper.FetchDrivers();
startManagingCursor(c);
// create an array to specify which fields we want to display
String[] from = new String[]{"FirstName"};
// create an array of the display item we want to bind our data to
int[] to = new int[]{android.R.id.text1};
// create simple cursor adapter
SimpleCursorAdapter adapter =
new SimpleCursorAdapter(this, android.R.layout.simple_spinner_item, c, from, to );
adapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item );
// get reference to our spinner
Spinner s = (Spinner) findViewById( R.id.spr_Driver1);
s.setAdapter(adapter);
}
Now it displays the FirstName and I've tried added "FirstName", "LastName" but it doesn't do anything different, I ideally want it to display the name in full on each spinner item. Is this even possible?
Any help would be great!
Thanks,
Chris
For this, you need to change the android.R.layout.simple_spinner_item and android.R.layout.simple_spinner_dropdown_item, as these layout items are able to display only one item in the dropdown list and on the spinner.
For your purpose, the best way is to create your own layout that has two items.
Here is a link about how to do it.

Android ListView update with SimpleCursorAdapter

Hey i use a listview for demonstrate entries which are stored in a database. I also have a EditText element and a button which adds the content of the EditText into the Database. To bind the view to the database content i use the SimpleCursorAdapter and following populate function:
private void populate() {
cursor = dbAdapter.getAllItems();
startManagingCursor(cursor);
String[] from = new String[] { DBAdapter.KEY_TASK };
int[] to = new int[] { android.R.id.text1 };
// Now create an array adapter and set it to display using our row
cursorAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, cursor, from, to);
list.setAdapter(cursorAdapter);
}
If i added a new entry, by clicking on the button i want to refresh the listview but this only works with the populate function and not with the common adapter function notifyDataSetChanged();. Do i have a bug or is this the right way to refresh a listview?
Have you seen this, tried the swap cursor method, or tried just simply calling setAdapter() again?
I had a similar issue where I could not get my list to update, and what I did was just create a refreshListView() method. Now you can call this initially from your onCreate(), AND anytime a user adds something to the DB. All it does is re-bind the listview to a cursor. With all the deprecating methods (requery()), and issues with notifyDataSetChanged(), I decided this was the easiest way.
Please refer this link...it works like charm
Update SimpleCursorAdapter while maintaining scroll position in ListView
for dynamic listview on scroll i added new item from database ..
I did mistake here ..
i was assigning new adapter for each time for same simplecursoradapter .
Instead of creating new adapter.
just use
adapter.changecursor(newcursorValue);
adapter.notifydatasetChanged();
lsMedicine1.setSelectionFromTop(lsMedicine1.getLastVisiblePosition()-20, 0);
You need to call swapcursor() before notifyDataSetChanged() on the adapter.

Spinners populated from database not registering selection

I'm having a problem implementing spinners and getting them to work the way I want. I have one spinner containing state abbreviations that is populated from an array. Depending on the state that the user selects, the application should perform a database query and populate the second spinner with locations of stores in the selected state.
The first spinner works fine, performs the query successfully and populates the second spinner. I want to get the value from the second spinner and display it in a toast message. Here is where the problem occurs. The second spinner is not registering clicks after it is initially filled.
In the example below, the user selects RI from the first spinner. The second spinner is populated and the first town in the spinner "COVENTRY" is shown in a toast message. The problem comes in when I try to select other towns from the 2nd spinner... although the towns are shown in the spinner, they aren't coming up in the toast message.
if (parent.getItemAtPosition(pos).toString().equals("RI")) {
HDHelper hdtable = new HDHelper(getApplicationContext());
hdtable.open();
Cursor c = hdtable.fetchRI();
if (c != null){
SimpleCursorAdapter hdadapter1 = new SimpleCursorAdapter(getApplicationContext(),
android.R.layout.simple_spinner_item, c, // Give the cursor to the list adapter
new String[] {c.getColumnName(2)}, // Map the column in the HD database to...
new int[] {android.R.id.text1}); // The view defined in the XML template
hdadapter1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
Spinner hdstoresspin = (Spinner) findViewById(R.id.hdstorespinner);
hdstoresspin.setAdapter(hdadapter1);
hdstoresspin.setOnItemSelectedListener(new MyOnItemSelectedListener());
String text = c.getString(c.getColumnIndex(hdtable.KEY_STORENUMBER));
Toast.makeText(parent.getContext(), text, Toast.LENGTH_LONG).show();
}
startManagingCursor(c);
hdtable.close();
}
Here is the relevant DBHelper section dealing with the above query:
public Cursor fetchRI() {
String RIquery = "SELECT * FROM HDStores WHERE state = 'RI' ORDER BY storenumber";
return mDb.rawQuery(RIquery, null);
}
UPDATE: I actually think the OnItemSelectedListeneris working properly. It is registering clicks, but no matter which value I click on, only the first value is reflected in the toast message. Again, any help would be greatly appreciated. Thank you.
I figured it would be something stupid that I missed. I went back to working on it again after a few days break and it jumped right out at me. The cursor needed to be finalized as well.

Categories

Resources