I am building a country picker dialog fragment in Android that shows a list of countries in a sectioned recycler view. First section shows favorites and second section shows the remaining countries. Each entry shows the name of the country and a star. By clicking the star the country moves from the non-favorite to the favorite section and vice versa.
Although I found a workaround I want to understand the reason for persistent values in a list of Country objects. First of all I have a list of country objects in a separate class:
Country.java
public class Country {
private String mCountryId;
private String mName;
private int mResourceId;
private boolean mIsFavourite;
public static final Country[] countries = {
new Country("4", "Afghanistan", R.drawable.zafghanistan, false),
new Country("8", "Albania", R.drawable.zalbania, false),
new Country("12", "Algeria", R.drawable.zalgeria, false),
new Country("20", "Andorra", R.drawable.zandorra, false),
new Country("24", "Angola", R.drawable.zangola, false),
new Country("28", "Antigua and Barbuda", R.drawable.zantigua_and_barbuda, false),
};
public Country(String countryId, String name, int resourceId, boolean isFavourite) {
mCountryId = countryId;
mName = name;
mResourceId = resourceId;
mIsFavourite = isFavourite;
}
public String getmCountryId () {
return mCountryId;
}
public String getmName() {
return mName;
}
public int getmResourceId() {
return mResourceId;
}
public boolean getmIsFavourite() {
return mIsFavourite;
}
public void setmIsFavourite(boolean mIsFavourite) {
this.mIsFavourite = mIsFavourite;
}
public static List<Country> createCountryList() {
List<Country> countriesArrayList = new ArrayList<>(Arrays.asList(countries));
return countriesArrayList;
}
}
The last value of the country object is a boolean that is used to store if the country is a favorite or not. I use this value to avoid constantly querying the local database.
In my dialog fragment you can see that I am initialising the countries list at the beginning, i.e. it gets all values of the Country class, which means that no country is a favorite at the beginning. Later I update this with the favorites stored in the database, but that is working correctly.
What I don't understand is the following observation: Assume I have 5 favorite countries and I close the dialog fragment by clicking outside of the fragment. Then I reopen the dialog fragment and the countries List should be initialised again. At least my check for !=null shows that the List is not initialised at this point. Then the initialisation with
countries = Country.createCountryList();
happens again. This means all favorite boolean values should be false like for the first opening of the dialog fragment. However those countries that were favorites show a boolean value of true! How is this possible? If the fragment would preserve the member variable the countries List should already be initialised at my check, but it is not. Are the values somewhere stored in another List or on the disk?
Here the relevant code of my dialog fragment: CountryDialogFragment.java
public class CountryDialogFragment extends DialogFragment {
List<Country> countries;
public static CountryDialogFragment newInstance() {
return new CountryDialogFragment();
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
//Inflate the layout for this fragment
//changed because of bug in support library, see codepath
Log.d(TAG, "onCreateDialog: countrydialogfragment ");
View view = getActivity().getLayoutInflater().inflate(R.layout.fr_dialog_country, null);
//create the dialog
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
alertDialogBuilder.setView(view);
AlertDialog dialog = alertDialogBuilder.create();
dialog.show();
//keyboard shall only appear when click into search field was made
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
dialog.getWindow().clearFlags(
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
//necessary to 'activate' onCreateOptionsMenu method
setHasOptionsMenu(true);
rvCountries = (RecyclerView) view.findViewById(R.id.rvCountries);
if (countries != null) {
Log.d(TAG, "countries initialised: countrydialogfragment");
} else {
Log.d(TAG, "countries not initialised: countrydialogfragment");
}
countries = Country.createCountryList();
//check to see how countries variable was initialised
for(int k=0; k < countries.size(); k++) {
Log.d(TAG, "favourite settings: " + countries.get(k).getmName() + " " + countries.get(k).getmIsFavourite());
}
}
}
Here is the part of the code in the Dialog Fragment that is used to change the favorite value in the countries list:
//listener for sending countries to non-favorites after the star was clicked
section1.setOnFavClickListener(new CountrySection.OnFavClickListener() {
@Override
public void onStarClick(final String countryIndex) {
//Log.d(TAG, "countryIndex: " + countryIndex);
Country countryFavChanged;
String favName;
for (Country country : countries) {
if (country.getmCountryId().equals(countryIndex)) {
countryFavChanged = country;
favName = countryFavChanged.getmName();
//update favorite status in country list
country.setmIsFavourite(true);
favCountries.remove(countryFavChanged);
section1.removeRow(favCountries);
nonFavCountries.add(countryFavChanged);
section2.addRow(nonFavCountries);
sectionAdapter.notifyDataSetChanged();
Log.d(TAG, "country removed from favs: " + favName);
break;
}
}
}
});
I am using this library for the sectioned recycler view: https://github.com/luizgrp/SectionedRecyclerViewAdapter
Code within my CountrySection.java file add/removing the favorites:
public void addRow(List items) {
Log.d(TAG, "addRow: ");
this.filteredCountryList.clear();
this.filteredCountryList.addAll(items);
}
public void removeRow(List items) {
Log.d(TAG, "removeRow: ");
this.filteredCountryList.clear();
this.filteredCountryList.addAll(items);
}
Probably needs to be optimised to add only the relevant country and not the whole list of countries.