Search code examples
javaandroidandroid-listfragmentandroid-configchanges

Android list fragment not updated when configuration changes


I'm making a simple app that adds a location to the list fragment in main page, and as I add more addresses to the list, whenever configuration changes, those addresses are carried over, which is expected.

However as you will see below, the empty list text shows up for some reason, and seems like when I add another new address hereafter, it will add to the very first place of the list.

Added new location

Configuration changed and empty list text appears

Adding new location brings to first place of the list

Below is my main activity :

public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {

private GoogleApiClient mGoogleApiClient;
private Location mLastLocation, mCurrentLocation;
private double currentLatitude, currentLongitude;
private String lastUpdateTime, addressMessage = null;
private AddressResultReceiver resultReceiver;
private MainList listFragment = new MainList();
//private boolean mRequestStatus = true;
private MaterialDialog dialog;
public boolean mAddressRequested = false;
private FragmentManager mFragmentManager;
private final String FRAGMENT_TAG = "main_list_tag";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addApi(LocationServices.API)
            .addOnConnectionFailedListener(this)
            .addConnectionCallbacks(this)
            .build();

    mFragmentManager = getFragmentManager();
    FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
    fragmentTransaction.add(R.id.list_frame, listFragment);
    fragmentTransaction.commit();

    dialog = new MaterialDialog(this)
            .setTitle("Select an address")
            .setPositiveButton("SELECT", new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    dialog.dismiss();
                    listFragment.list.add(addressMessage);
                    listFragment.mAdapter.notifyDataSetChanged();
                }
            })
            .setNegativeButton("CANCEL", new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    dialog.dismiss();
                }
            });

    Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar);
    setSupportActionBar(toolbar);

    FloatingActionButton floatingActionButton = (FloatingActionButton) findViewById(R.id.fab_button);

    //LayoutInflater inflater = LayoutInflater.from(getApplicationContext());

    floatingActionButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (checkAirPlaneMode(getApplicationContext())) {
                Toast.makeText(getApplicationContext(), "Air Plane Mode is ON, Please turn off to get location", Toast.LENGTH_LONG).show();
            }
            else if (!checkNetwork()) {
                Toast.makeText(getApplicationContext(),"Unable to reach network, please check network settings",Toast.LENGTH_LONG).show();
            }
            else if (!checkLocationSettings(getApplicationContext())) {
                showLocationSettings();
            }
            else {
                startAddressLookUp();
                mAddressRequested = true;
                dialog.setMessage(addressMessage);
                dialog.show();
            }
        }
    });

}


@Override
public void onStart() {
    super.onStart();
    if (mGoogleApiClient == null) {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addOnConnectionFailedListener(this)
                .addConnectionCallbacks(this)
                .build();
    }
    mGoogleApiClient.connect();
}

@Override
protected void onPause() {
    super.onPause();
    LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}

@Override
public void onResume() {
    super.onResume();
    if(mGoogleApiClient.isConnected()) {
        LocationRequest locationRequest = createLocationRequest();
        startLocationUpdates(locationRequest);
    }
}

And list fragment class:

public class MainList extends ListFragment implements AdapterView.OnItemClickListener {

private int stateInt;
private final String FRAGMENT_KEY = "saved_fragment";
ArrayList<String> list = new ArrayList<>();
ArrayAdapter<String> mAdapter;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    return inflater.inflate(R.layout.list_fragment, container, false);

    /*ListView view = (ListView) v.findViewById(android.R.id.list);
    view.setEmptyView(v.findViewById(android.R.id.empty));

    return view;*/
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    setRetainInstance(true);

    getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);

    mAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, list);

    setListAdapter(mAdapter);
    //mAdapter.notifyDataSetChanged();
}

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    Toast.makeText(parent.getContext(), "Item Pressed!", Toast.LENGTH_LONG).show();
}

}

How can avoid this? Am I missing the save application state or something else? Any help would be appreciated! Thanks in advance!

Thanks, Paul


Solution

  • The onCreate method is called for every orientation change. And in the method you are adding the fragment again. That is why you get this behavior.

    Check this for the correct way to do this. Handling Configuration Changes with Fragments

    FragmentManager fm = getFragmentManager();
    mTaskFragment = (TaskFragment) fm.findFragmentByTag(TAG_TASK_FRAGMENT);
    
    // If the Fragment is non-null, then it is currently being
    // retained across a configuration change.
    if (mTaskFragment == null) {
       mTaskFragment = new TaskFragment();
       fm.beginTransaction().add(mTaskFragment, TAG_TASK_FRAGMENT).commit();
    }