Cannot read country code selected in a spinner Android

738 views Asked by At

I am working on an app in which users have to select a country code, i was successful in creating a spinner for the said purpose as shown in this link:
Creating a spinner for choosing country code But i am getting problem in reading the value selected in the spinner.

{
               String abc = onCountryPickerClick();//abc is always null 
}  
    public String onCountryPickerClick (){
         ccp.setOnCountryChangeListener(new CountryCodePicker.OnCountryChangeListener() {
             @Override
             public void onCountrySelected() {
                 selected_country_code = ccp.getSelectedCountryCodeWithPlus();
             }

         });
         return  selected_country_code;
    }
2

There are 2 answers

1
Patryk Goworowski On BEST ANSWER

When String abc = onCountryPickerClick(); is being invoked, the selected_country_code value will be assigned to abc.

When your CountryCodePicker.OnCountryChangeListener's onCountrySelected() method is being invoked, the ccp.getSelectedCountryCodeWithPlus();'s value gets assigned to selected_country_code. Since String is immutable, changing selected_country_code's value won't change the value of abc, nor the return selected_country_code; will be invoked.

One of possible solutions would be to change your CountryCodePicker.OnCountryChangeListener anonymous implementation to assign the selected country value to abc e.g.

@Override
public void onCountrySelected() {
       selected_country_code = ccp.getSelectedCountryCodeWithPlus();
       abc = selected_country_code
}
2
Fred On

Callbacks are not synchronous. Unfortunately, you cannot simply do String abc = onCountryPickerClick(); because what you are returning is something that is not yet set. Let's go through your code:

ccp.setOnCountryChangeListener(
     new CountryCodePicker.OnCountryChangeListener() {
         @Override
         public void onCountrySelected() {
             selected_country_code = ccp.getSelectedCountryCodeWithPlus();
         }
     });

The code seems to say that when the country is selected in the spinner, you assign the value of selected_country_code. Assuming this is an action triggered by the user, when you call String abc = onCountryPickerClick();, how can you be sure the user has selected anything? This is the issue. You cannot be sure that the user has already selected the option and returning the value is not enough.

You can solve this in many ways. You can for example keep propagating the callback:

public void onCountryPickerClick(OnCountryChangeListener listener){
     ccp.setOnCountryChangeListener(listener);
}

// Anywhere you call this
onCountryPickerClick(new CountryCodePicker.OnCountryChangeListener() {
         @Override
         public void onCountrySelected() {
             // Here do whatever you want with the selected country
         }
     });

The above approach is not very different than what you have now. There are other options. You could use java observables i.e.:

class CountryCodeObservable extends Observable {
  private String value;

  public CountryCodeObservable(String value) {
    this.value = value;
  }

  public void setCountryCode(String countryCode) {
    value = countryCode;
    setChanged();
    notifyObservers(value);
  }
}

public CountryCodeObservable onCountryPickerClick(){
  CountryCodeObservable retValue = new CountryCodeObservable("");

  ccp.setOnCountryChangeListener(
     new CountryCodePicker.OnCountryChangeListener() {
         @Override
         public void onCountrySelected() {
             retValue.setCountryCode(ccp.getSelectedCountryCodeWithPlus());
         }
     });

  return retValue;
}

// Then when calling this method you can do something like:
CountryCodeObservable observable = onCountryPickerClick();

observable.addObserver((obj, arg) -> {
   // arg is the value that changed. You'll probably need to cast it to
   // a string
});

The above example lets you add more than one observable. It might be too much for your use case, I just thought it illustrates another approach and also the asynchronicity of this situation.

Again, there are even more ways to solve this, the key is that you can't simply return a string and hope it changes when the user selects anything.