Order of OnItemSelectedListener Calls After OnCreate - android

I have two spinners in an Activity where the second Spinner's selection set is based on what the user picked for the first Spinner. I use a private class variable in the Activity which is set in the top Spinner's OnItemSelectedListener and then referenced in the bottom Spinner's OnItemSelectedListener to obtain the correct selection set.
This almost always works, but sometimes (mainly when app was run, not exited, and then started again by a user click some long time later) I get a null pointer exception in the second Spinner's OnItemSelectedListener due to this local variable not being set. This indicates to me that after the OnCreate that the second Spinner's OnItemSelectedListener was called before the first Spinner's.
Is there any method to force a certain order in the listeners being fired or is there a better design approach to handle this second Spinner's dependency on the first Spinner?
Example code:
package com.crashtestdummylimited.navydecoder;
public class Test extends Activity {
// Variable that at times is still null
private ReferenceData referenceData;
private void setupSpinnerFromArray (int spinnerId, String stringArray[], OnItemSelectedListener listener) {
Spinner spinner = (Spinner) findViewById(spinnerId);
ArrayAdapter <CharSequence> adapter = new ArrayAdapter <CharSequence>(
this, android.R.layout.simple_spinner_item, stringArray);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(listener);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_screen);
// Setup Top (main) Spinner
Spinner spinner1 = (Spinner) findViewById(R.id.mainDecodeSpinner);
ArrayAdapter<CharSequence> adapter1 = ArrayAdapter.createFromResource(
this, R.array.level0_list_array, android.R.layout.simple_spinner_item);
adapter1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner1.setAdapter(adapter1);
spinner1.setOnItemSelectedListener(new MainDecoderItemSelectedListener());
// Setup Bottom (dependent) Spinner
setupSpinnerFromArray(R.id.secondaryDecodeSpinner, R.array.level1_list_array, new SecondaryDecoderItemSelectedListener());
}
public class MainDecoderItemSelectedListener implements OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent,
View view, int pos, long id) {
String selectedString = parent.getItemAtPosition(pos).toString();
if (selectedString.equals("AAA")){
// Problem variable is set
referenceData = new RatingCodes();
setupSpinnerFromArray(R.id.secondaryDecodeSpinner, referenceData.getKeys(), new SecondaryDecoderItemSelectedListener());
}
else if (selectedString.equals("BBB")){
// Problem variable is set
referenceData = new IMSCodes();
setupSpinnerFromArray(R.id.secondaryDecodeSpinner, referenceData.getKeys(), new SecondaryDecoderItemSelectedListener());
}
// TODO: Improve what occurs if no match which should not occur
}
public void onNothingSelected(AdapterView<?> parent) {
// Do nothing.
}
}
public class SecondaryDecoderItemSelectedListener implements OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent,
View view, int pos, long id) {
String key = parent.getItemAtPosition(pos).toString();
// **** referenceData being null at this point has caused crashed ****
String value = referenceData.getValue(key);
// ... Update text on activity screen ...
}
public void onNothingSelected(AdapterView<?> parent) {
// Do nothing.
}
}
}

public void onItemSelected(AdapterView<?> parent,View view, int pos, long id)
{
if(pos == 0)
{ //when it loads on onCreate() then pos is always 0
//donothing
}
else
{ //If user manually select item
//do what you need to do on manual user selection
}
}

Related

android: spinner not updating my view when notifyDataSetChanged() is called

I am trying to update the spinner view by calling notifyDataSetChanged(). But its not updating.
The below is my Activity:
public class DisplayArchive2 extends AppCompatActivity {
List<String> yearslist;
Spinner spinner;
ArrayAdapter<String> dataAdapter;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.archive2);
spinner = (Spinner) findViewById(R.id.year_spinner);
yearslist = new ArrayList<String>();
yearslist.add("2017");
yearslist.add("2016");
yearslist.add("2015");
yearslist.add("2014");
yearslist.add("2013");
dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item,yearslist);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(dataAdapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
yearslist.clear();
yearslist.add("2010");
yearslist.add("2009");
yearslist.add("2008");
yearslist.add("2007");
yearslist.add("2006");
dataAdapter.notifyDataSetChanged();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
}
The list of years is not changing on selecting any year.
It looks like below
Try this use dataAdapter2.setNotifyOnChange(true); its working fine i have tested it my device
void setNotifyOnChange (boolean notifyOnChange)
Control whether methods that change the list (add(T), addAll(Collection), addAll(Object[]), insert(T, int), remove(T), clear(), sort(Comparator)) automatically call notifyDataSetChanged(). If set to false, caller must manually call notifyDataSetChanged() to have the changes reflected in the attached view. The default is true, and calling notifyDataSetChanged() resets the flag to true.
CODE
List<String> yearslist;
Spinner spinner;
ArrayAdapter<String> dataAdapter2;
spinner = (Spinner) findViewById(R.id.year_spinner);
yearslist = new ArrayList<String>();
yearslist.add("2017");
yearslist.add("2016");
yearslist.add("2015");
yearslist.add("2014");
yearslist.add("2013");
dataAdapter2 = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item,yearslist);
dataAdapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(dataAdapter2);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (position == 0) {
} else {
yearslist.clear();
yearslist.add("2010");
yearslist.add("2009");
yearslist.add("2008");
yearslist.add("2007");
yearslist.add("2006");
dataAdapter2.setNotifyOnChange(true);
dataAdapter2.notifyDataSetChanged();
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
As per my understanding. You are notifying the adapter inside onItemSelected(). In case of Spinner adapter initialization onItemSelected() will get called once for first time . So the list you will get in Spinner is always the new one(i.e 2006-2010) never the first one(i.e 2013-2017).
So if you do notify adapter on some other action or maybe avoid the first call to onItemSelected() your code will work fine .

Cannot get current spinner position with setOnItemSelectedListener

I am trying to retrieve the spinner's selected position. The values inside the spinner are of type String and I am using setOnItemSelectedListener to change a class String variable to the one that has been selected and use it later on:
spinner = (MaterialBetterSpinner) myToolbar.findViewById(R.id.spinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line,socialMediaOptions);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
socialMedia = parent.getItemAtPosition(position).toString();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
private void sendPost(){
Log.v(TAG, socialMedia);
}
The problem is that the variable does not change when an item is selected, it seems like onItemSelected is not being called when there is a change in the spinner selection
See this thread:
https://github.com/Lesilva/BetterSpinner/issues/42
There said that BetterSpinner extends EditText, that's why onItemSelectedListener is not being called. You should use TextChangedListener instead.
Hope your socialMediaOptions are string array like this
socialMediaOptions={"FB","TWIT","IN"}
then
// Specify the layout to use when the list of choices appears
add this line
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
socialMedia = socialMediaOptions[position];
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});

Show the value of spinner in string instead of integer?

I want to show the value of spinner in string instead of integer. Right now it is showing integer like '0','1'.
Setting activity:
public class Setting extends Activity {
bloodtype = (Spinner) findViewById(R.id.spinner2);
ArrayAdapter<String> adapter2 = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item,getResources().getStringArray(R.array.blood_groups_arrays));
adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
bloodtype.setAdapter(adapter2);
bloodtype.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
/**
* Called when a new item is selected (in the Spinner)
*/
public void onItemSelected(AdapterView<?> parent,
View view, int position, long id) {
sharedpreferences.edit().putString(BloodType, parent.getItemAtPosition(position).toString()).commit();
}
public void onNothingSelected(AdapterView<?> parent) {
// Do nothing.
}
});
if(sharedpreferences.contains(BloodType)) {
bloodtype.setSelection(sharedpreferences.getString(BloodType, "DEFAULT"));
}
}
Calling its value in main activity:
if(sharedpreferences.contains(Setting.BloodType)) {
show.setText(""+sharedpreferences.getString(Setting.BloodType, "DEFAULT"));
}
In order to store a value of array you populated your spinner with in SharedPreferences use the following line in onItemSelected() method:
sharedpreferences.edit().putString(BloodType, parent.getItemAtPosition(position).toString()).commit();
Note: BloodType has to be of String type, because it plays a role of a key in key-value pair of SharedPreferences.
Taken from my working project it should work:
adapterSpinner = new ArrayAdapter<String>(yourContenxt,
android.R.layout.simple_list_item_1, yourDataSource);
spinnerProfileType.setAdapter(adapterSpinner);
As you are using a string array you can set the spinner items in xml too by using:
android:entries = "#array/your_string_entry"

Android Spinners, changing Adapters

Alright, so I'm new to Android programming, so far my experience has been quite interesting and challenging. But I fear I have now encountered the first problem I'm not able to overcome on my own.
Simply put, all I want to do is have 2 Spinners:
1 for country selection
1 for province/state selection
What I want to accomplish is that when the user selects his/her country the province/state Spinner is updated with the correct adapter. Currently I'm only using 2 country for testing purposes.
When I launch the Activity, I get an exception and my app crashes.
Here's my code, any pointers would be appreciated !
public class ManageAccountActivity extends Activity {
final ArrayAdapter<CharSequence> adapterSexe = ArrayAdapter.createFromResource(ManageAccountActivity.this, R.array.sex_array_fr, android.R.layout.simple_spinner_item);
final ArrayAdapter<CharSequence> adapterProvince = ArrayAdapter.createFromResource(ManageAccountActivity.this, R.array.province_array_fr, android.R.layout.simple_spinner_item);
final ArrayAdapter<CharSequence> adapterStates = ArrayAdapter.createFromResource(ManageAccountActivity.this, R.array.state_array_fr, android.R.layout.simple_spinner_item);
final ArrayAdapter<CharSequence> adapterCountry = ArrayAdapter.createFromResource(ManageAccountActivity.this, R.array.country_array_fr, android.R.layout.simple_spinner_item);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.account_management);
Spinner spinSexe = (Spinner) findViewById(R.id.spin_sex);
Spinner spinProvince = (Spinner) findViewById(R.id.spin_province);
Spinner spinCountry = (Spinner) findViewById(R.id.spin_country);
adapterSexe.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
adapterProvince.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
adapterStates.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
adapterCountry.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinSexe.setAdapter(adapterSexe);
spinProvince.setAdapter(adapterProvince);
spinCountry.setAdapter(adapterCountry);
spinCountry.setOnItemSelectedListener(new CountryOnItemSelectedListener());
}
public class CountryOnItemSelectedListener implements OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
setContentView(R.layout.account_management);
Spinner spinProvince = (Spinner) view.findViewById(R.id.spin_province);
if (parent.getItemAtPosition(pos).toString().equals("Canada")) {
spinProvince.setAdapter(adapterProvince);
} else {
spinProvince.setAdapter(adapterStates);
}
}
public void onNothingSelected(AdapterView parent) {
// Do nothing.
}
}
}
Here's the LogCat message I'm getting.
01-10 20:41:01.024: E/AndroidRuntime(1275):
java.lang.RuntimeException: Unable to instantiate activity
ComponentInfo{gggolf.android.minutegolf/gggolf.android.minutegolf.ManageAccountActivity}:
java.lang.NullPointerException
You cannot instantiate your ArrayAdapter directly on class attribut, because createFromResource() use Context, and it's not exists at this time, do it in onCreate() methode instead.
In addition, you get spin province wrong in your listener, you can't call findViewById on view local variable, because it's not your layout, but an inflate of android.R.layout.simple_spinner_item
The good way:
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
Spinner spinProvince = (Spinner) findViewById(R.id.spin_province);
if (parent.getItemAtPosition(pos).toString().equals("Canada")) {
spinProvince.setAdapter(adapterProvince);
} else {
spinProvince.setAdapter(adapterStates);
}
}
Try having your Activity implement AdapterView.OnItemSelectedListener itself. Notice I've moved the Spinners and left out some of your code and replaced it with comments - make sure you include it where necessary...
public class ManageAccountActivity extends Activity
implements AdapterView.OnItemSelectedListener {
// Your ArrayAdapters as before
Spinner spinSexe = null;
Spinner spinProvince = null;
Spinner spinCountry = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.account_management);
spinSexe = (Spinner) findViewById(R.id.spin_sex);
spinProvince = (Spinner) findViewById(R.id.spin_province);
spinCountry = (Spinner) findViewById(R.id.spin_country);
// Call setDropDownViewResource on your ArrayAdapters
// Call setAdapter on your Spinners
spinCountry.setOnItemSelectedListener(this);
}
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
if (parent.getItemAtPosition(pos).toString().equals("Canada")) {
spinProvince.setAdapter(adapterProvince);
} else {
spinProvince.setAdapter(adapterStates);
}
}
public void onNothingSelected(AdapterView parent) {
}
}
Why do you have setContentView(R.layout.account_management); in your onItemSelected() method? That should not be necessary.
Furthermore, you should instantiate your adapters in the onCreate() method of your activity, and pass your actual activity instance as the context.
And the code for retrieving the Spinner object in the select listener should be changed from
Spinner spinProvince = (Spinner) view.findViewById(R.id.spin_province);
into
Spinner spinProvince = (Spinner) findViewById(R.id.spin_province);
Calling findViewById() on the local view object in your select listener will return NULL because the view does not contain the Spinner.

How to get spinner string value on android?

I have created a spinner and the items of spinner comes from database. However, When I use
public class MyOnItemSelectedListener implements OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent,
View view, int pos, long id) {
typeOFBCard = contactSpinner.getSelectedItem().toString();
}
public void onNothingSelected(AdapterView parent) {
// Do nothing.
}
}
When I call this listener and try to pick the chosen string of the spinner i get a reference of the sglite something like:
android.database.sqlite.SQLiteCursor#40535568
This is the return value of typeOfBCard.
However, on the spinner I can see normal string like "Work".
Here is how I initialized the spinner :
contactSpinner = (Spinner) findViewById(R.id.contactSpinner);
mobileText =(EditText) findViewById(R.id.mobileText);
mDbHelper = new DbAdapter(this);
mDbHelper.open();
cursor = mDbHelper.fetchAllBusinessCards();
startManagingCursor(cursor);
context =this;
contactSpinner.setOnItemSelectedListener(new MyOnItemSelectedListener());
How ever on the spinner I can see normal string like "Work"
That is because you configured an Adapter on the Spinner, and the Adapter is pulling data out of the Cursor to display.
How to get spinner string value on android?
There is no "spinner string value". Spinners don't have strings. They have views. Those views might be instances of TextView, or they might be instances of ImageView, or they might be instances of a LinearLayout holding onto a TextView and an ImageView, or...
If you want to get data out of the Cursor, call getString() on the Cursor.
Every row in a spinner is a view but it's also a value/object from your source.
Try
public class MyOnItemSelectedListener implements OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent,
View view, int pos, long id) {
// Parent == where the click happened.
typeOFBCard = parent.getSelectedItem().toString();
}
public void onNothingSelected(AdapterView parent) {
// Do nothing.
}
}

Categories

Resources