This question already has answers here:
saving spinner state using sharedpreferences in android
(1 answer)
Shared Preference & Spinner Not Maintaining State
(4 answers)
Closed 8 months ago.
I'm doing an Android app which can get data from a web service & load it into spinner. I need to maintain the selected data state of the spinner while I go to some screen & come back. For example, if I'm getting data from the web service as 1.apple 2.orange 3.grapes & loading it into the spinner, then I select orange. When I go to some other screen & come back, the selected spinner data should be orange. But it again loads data from the server into the spinner. Can anybody help me to resolve this?
My code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
if (Constants.SPINNER != null ) {
spinner.setSelection( Constants.SPINNER);
} else {
//WebCall here for getting data
}
//...
spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent,
View view, int arg2, long arg3) {
Constants.SPINNER = spinner.getSelectedItemPosition();
In Constant class:
public static Integer SPINNER="";
You can follow the below procedure:
You need to save state of your spinner so this would be helpful to you.
1.) Apply this after creating spinner object
sectionNameSpinner.setSelection(getPersistedItem());
2.) Create these methods according to you to save the state of your spinner selected item
private int getPersistedItem() {
String keyName = makePersistedItemKeyName();
return PreferenceManager.getDefaultSharedPreferences(this).getInt(keyName, 0);
}
protected void setPersistedItem(int position) {
String keyName = makePersistedItemKeyName();
PreferenceManager.getDefaultSharedPreferences(this).edit().putInt(keyName, position).commit();
}
private String makePersistedItemKeyName() {
return currentUserName + "_your_key";
}
3.) Set its state as the spinner selection changed:
sectionNameSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View view, int position, long itemId) {
setPersistedItem(position);
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
When you "go to some other screen" you should do so via a new activity. Then, after you finish that new activity, the spinner selection activity will resume and the selection state will be as it was prior to starting the second activity.
Make sure you are not hitting the webservice in OnResume() of your activity.
Make sure you are not finishing the current activity by calling finish() before proceeding to the next activity.
And check whether data available or not before web hit (here you can avoid unnecessary web hits)
Related
I have an Activity with a Spinner. This Activity will load information from the internet based on the Spinner selection and show it in this Activity. When the first time the Activity is launched, the Spinner will be selected by default. I use Spinner#setOnItemSelectedListener so that each time the Spinner is selected, a method which will load information from the internet will be triggered.
#Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
String option = (String) parent.getItemAtPosition(pos);
loadInfoFromInternet(option);
}
When the orientation of the phone is changed, the Activity will be destroyed and recreated. I've stored the Spinner information and also the information I got from the internet in the savedInstanceState's bundle. With it, I managed to save the state of the Spinner and the info from internet.
The problem is with the info I got from the internet. When the orientation changes, Spinner will be recreated and select an option. This will trigger OnItemSelectedListener which will call onItemSelected. The loadInfoFromInternet will be triggered again. It makes my data which I stored in savedInstanceState be replaced.
What I want is when the orientation changes, I want the Spinner not to trigger loadInfoFromInternet so that I can show the information from previous state instead of loading from internet again.
Initially, I come up with the following idea:
private boolean isNewState = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
if (savedInstanceState == null) {
isNewState = true;
}
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
String option = (String) parent.getItemAtPosition(pos);
if (isNewState) {
loadInfoFromInternet(option);
}
}
With the above solution, when the orientation changes, the information is not loaded from the internet again. That's what I want, but, when I select another option, the loadInfoFromInternet will not be triggered since it's not a new state (isNewState = false). This is not what I want.
What you described in your question sounds on track. Inside your onCreate() method you can check the Bundle parameter which gets passed in. If the bundle is not null, then you can assume that you have saved state for your spinner and you can load that state.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ...
if (savedInstanceState == null) {
isNewState = true;
}
else {
int sIndex = savedInstanceState.getInt("S_INDEX");
Spinner spinner = (Spinner) findViewById(R.id.yourSpinner);
spinner.setSelection(S_INDEX);
}
}
and add logic to onSaveInstanceState() to save the index state of the spinner:
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
Spinner spinner = (Spinner) findViewById(R.id.yourSpinner);
int sIndex = spinner.getSelectedItemPosition();
savedInstanceState.putInt("S_INDEX", sIndex);
}
Note that onSaveInstanceState() will get called each time your phone changes orientation. All you need to do is store the state of the activity in the Bundle to persist it across changes.
native English speaker, so I'd say sorry about my bad English skills to you guys.
I've been studing Android since 5 weeks ago. I tried to implement a spinner and my mentor asked why the onNothingSelected method is needed. I had nothing to say.
So, why do I need that method?? Can you reply it?
Following code is my spinner. It does correctly what I intended.
public class SpinnerViewPractice extends Activity {
private Spinner spinner;
private String spinner_value = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.spinnerviewpractice);
spinner = (Spinner)findViewById(R.id.spinner1);
String[] str = {"","good", "dislike", "like", "hate", "moderate"};
spinner.setPrompt("Set Text");
ArrayAdapter<String> list = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, str);
spinner.setAdapter(list);
spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
TextView tv = (TextView)arg1;
spinner_value = tv.getText().toString();
if(spinner_value.length() == 0)
{
spinner_value = "Nothing";
}
Toast.makeText(SpinnerViewPractice.this, spinner_value, Toast.LENGTH_SHORT).show();
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
Toast.makeText(SpinnerViewPractice.this, "NothingSelected", Toast.LENGTH_SHORT).show();
}
});
}
}
As the documentation describes:
Callback method to be invoked when the selection disappears from this view. The selection can disappear for instance when touch is activated or when the adapter becomes empty.
This means that the method is called whenever the currently selected item is removed from the list of available items. As the doc describes, this can occur under different circumstances, but generally if the adapter is modified such that the currently selected item is no longer available then the method will be called.
This method may be used so that you can set which item will be selected given that the previous item is no longer available. This is instead of letting the spinner automatically select the next item in the list.
From the doc here.
onNothingSelected is a Callback method to be invoked when the selection disappears from this
view. The selection can disappear for instance when touch is activated
or when the adapter becomes empty.
I think it pretty much answers your question. So if your spinner disappear for other reason except selecting the item then onNothingSelected will be called. So as it's name tells it is needed to find out when nothing is selected
I have implemented multiple(seven) spinners and populated them with three options: Yes, No, and Unknown. And "Unknown" is the default option. Now I want to know whether user clicked spinner or not. Since the default option can also be a valid answer, I could not work with getSelectedItemPosition() in Spinner class.
All I want to know is whether user clicked that particular spinner or not, so that I can generate alert message depending on this Info.
The first thing you should do is read the Spinners guide on the Android developer site. Having done that, you'll find this handy example:
public class MySpinnerActivity extends Activity implements OnItemSelectedListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Spinner spinner = (Spinner) findViewById(R.id.spinner);
spinner.setOnItemSelectedListener(this);
}
public void onItemSelected(AdapterView<?> parent, View view,
int pos, long id) {
// An item was selected. You can retrieve the selected item using
// parent.getItemAtPosition(pos)
}
public void onNothingSelected(AdapterView<?> parent) {
// Another interface callback
}
}
Simpy,
First Set OnItemSelectedListener to each Spinner and then check in method,
if you have more spinner then getSelectedItem() using below code inside onItemSeleted Method,
String str1= (String) spinner1.getSelectedItem().toString();
String str2= (String) spinner2.getSelectedItem().toString();
I have a simple app where the user selects one of the US states and the state selected is to be used to list all of the counties in that state. In onCreate, I built an arrayadapter called Stateadapter, and set it to the spinner object "spinState". I then initialized a listener class StateOnItemSelectedListener. Outside of onCreate, I have the StateOnItemSelectedListener class that will read which State was selected in the spinner, and then perform the rest of the app's tasks.
I have two problems: when single stepping thru the code in debug mode, the "parent.getItemAtPosition(pos).toString" does not return the string value of the selected state (though numerous web examples suggest this should work).
Second, when running, the app fires the listener when going thru onCreate and all appears well until the user selects the spinner on the ui, and the app then does a force close.
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
spinState = (Spinner)this.findViewById(R.id.spinState);
ArrayAdapter<String> Stateadapter = new ArrayAdapter<String> (this,android.R.layout.simple_spinner_item, array_spinState);
Stateadapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinState.setAdapter(Stateadapter);
spinState.setOnItemSelectedListener(new StateOnItemSelectedListener());
}
public class StateOnItemSelectedListener implements OnItemSelectedListener
{
public void onItemSelected(AdapterView<?> parent, View itemSelected, int pos, long id)
{ State = spinState.getItemAtPosition(pos).toString();
//Do Stuff base on State;
}
public void onNothingSelected(AdapterView<?> parent)
{ //Do nothing here
}
}
Try doing what they do in the Spinner Tutorial, they create the adapter in a different way, but eventually they use the same code to access to selected item and it works.
What is the error in log cat from the force close, and what getItemAtPosition does return?
I'm creating a spinner and I've added an OnItemSelectedListener to it.
However I've noticed that it fires on create.
Now I was wondering if there was a way to ignore/discard it.
I know I could use a boolean value, but that's a bit "dirty".
Here is my solution.
I need to ignore the first item selection event because there is a dependency between the Route Grade Spinner and the Route Checkbox.
And all my controls are setup based on a previous visit to the activity.
// Used to count the number of times the onItemSelected gets fired
private int mGradeSelectionCount = 0;
private void attachHandlers() {
OnItemSelectedListener gradeRangeSelectionMadeListener;
gradeRangeSelectionMadeListener = new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapter, View view, int position, long id) {
// If the counter is 0 then we can assume that it is android firing the event
if (mGradeSelectionCount++ < 1) {
return;
}
if (mCmbGradeFrom.getSelectedItemPosition() == 0) {
// Uncheck the Route checkbox
mChkTypeRoute.setChecked(false);
} else {
// Check the Route checkbox
mChkTypeRoute.setChecked(true);
}
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// Dont care, keep the same values as before
}
};
mCmbGradeFrom.setOnItemSelectedListener(gradeRangeSelectionMadeListener);
mChkTypeRoute.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (!isChecked) {
mCmbGradeFrom.setSelection(0);
mCmbGradeTo.setSelection(0);
}
}
});
}
This may help you.
#Override
public void onItemSelected( AdapterView<?> parent, View view, int position, long id)
{
if(view!=null && view.getId()!=0){
//do your code here to avoid callback twice
}
}
You should not attempt to prevent the call to the OnItemSelectedListener.
By default, Android Spinners select the first item returned by the Adapter, and therefore the OnItemSelectedListener is called to trigger some action on that item.
I would advise that the first item in your Spinner Adapter be a blank item, and your OnItemSelectedListener can ignore that blank item based on its id.
If anyone else comes across this question, it may be worth having a look at a related question I asked a while ago, which has several answers with good ideas on how to work around this issue.
Well I think I found nice solution for me, I had it in mind from start but...
I have custom wrapper class based on android Handler , that is called DoLater, and also there is custom Adapter based on Listener so you cant copy paste this but you will get idea. Dangerous thing is just that somehow delay 500 can be to long and View can be already destroyed (when user do some wired stuff quickly or phone gets slow...) so DoLater cares of that so it is not called when activity is not resumed. But this way OnItemSelectedListener is not fired on create.
public void onResume() {
super.onResume();
new DoLater(this, 500) {
public void run() {
new OnSpinnerSelectedAdapter(getBowSpinner()) {
protected void onItemSelected(int position) {
onBowSelected(position);
}
};
}
};
}