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?
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
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)
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 included my ListAdapter in my EMPLOYEE class.And list1 contains the values of Empname,
Eno,Salary fetched from webservices.Now after displaying the 5 records in the employee
screen...when I click on Depatrment Activity and come back to Employee ... the initial
5 records are appended to the list and now 10 records are present and so on .... the process is going on like this...
Please help me so as no duplicates are appended and it has to refresh the list.
Note : clear() or notifydatasetchanged(), invalidate() are not working.
ListAdapter adapter = new SimpleAdapter(this, list1,
R.layout.employee, new String[] { "EmpName","Eno", "Salary" }, new int[]
{R.id.ename, R.id.eno,R.id.sal});
setListAdapter(adapter);
Listview lv = getListView();
lv.setTextFilterEnabled(true);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
pos = position;
registerForContextMenu(getListView());
}
});
TextView tvdept = (TextView) findViewById(R.id.Department);
tvdept.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
startActivity(new Intent(Employee.this, Department.class));
}
});
Without seeing more code, it's difficult to be sure, but I'll hazard a guess...
When you leave an activity and come back, the framework tries to restore you to where you were using the savedInstanceState bundle. It uses this to re-create where you last were in that activity. It sounds like you have set up the list in the onCreate method and haven't checked for a savedInstanceState bundle, so when you come back to the activity the framework is restoring your list and then proceeds into your code and re-creates the list (in this case adding the same data again).
Try wrapping your list creation code in an if that checks for the existence of the savedInstanceState bundle.
Like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
// do your list setup here
}
}
Using that, if you come back to the activity and the framework saved your state, it will simply restore it and not run through your list creation code.
I know this doesn't answer the actual question, but it should solve the root issue (duplicating list data on return to activity).