Search code examples
androidandroid-loadermanager

LoaderManager restartLoader does not work as expected when switching to alternative layout


My app has a selector and a ListFragment. In portrait layout a spinner is used as the selector; in landscape a listview is used. When an item is selected, the listener would refresh the ListFragment's contents based on the selected item. Below is the code:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_card_logs);
    ...
    spinner = (Spinner)findViewById(R.id.card_name);
    listView = (ListView)findViewById(R.id.card_list);
    if (spinner != null)
        spinner.setOnItemSelectedListener(this);
    if (listView != null) {
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                CardLogFragment.Entity selected = (CardLogFragment.Entity)listView.getAdapter().getItem(position);
                if (selected != null) {
                    Bundle bundle = new Bundle();
                    bundle.putLong(CardLogFragment.CARD_ID, id);
                    CardLogFragment fragment = (CardLogFragment)getFragmentManager().findFragmentById(R.id.cardlog);
   // this does not work after portrait->landscape
                    getLoaderManager().restartLoader(0, bundle, fragment);
   // this always works  
                 CardLogsActivity.this.getSupportActionBar().setTitle(
                            selected.getName()
                    );
                }
            }
        });
    }

@Override
public void onResume() {
    super.onResume();
    ArrayAdapter<CardLogFragment.Entity> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    // populate the adapter
    adapter.add(...);
    adapter.add(...);
    adapter.add(...);
    if (spinner != null) {
        spinner.setAdapter(adapter);
            spinner.setSelection(1);
    }
    else if (listView != null) {
        listView.setAdapter(adapter);
    }
}

When I start the app in portrait mode, it works. I change to landscape mode the widgets are laid out again nicely. But when I click on an item of the listview, the list contents are not updated, only the app bar's title is changed. So it is evident that getLoaderManager( ).restartLoader(0, bundle,f ragment) has been called but with no effect.

If I start the app in landscape mode, everything is fine - the list contents are updated. But when changed to portrait, the contents are not updated in the portrait's listfragment.

BTW, the fragment in the 2 layout files have the same id, @+id/cardlog under res/layout/ and @id/cardlog under res/layout-land/. Is this correct?


Solution

  • I think your main issue is that you use LoaderManager of the enclosing Activity, while passing in a child Fragment as a callback.

    There is a reason why Fragment and Activity have separate LoaderManager - they have different (and potentially unrelated) lifecycles.

    If you need to have Fragment as a callback, you need to put all the code related to Loaders into that Fragment and use its own LoaderManager.