1

In my Activity, I am loading fragments and adding them to the backstack as the user clicks on items. This works fine and the backstack loads well.

Unfortunately, when I rotate the device, the activity is blank. I have tried everything possible on SO and on Google.

I tried managing the navigation myself by simply replacing the fragments as the user clicks and handling the back as nav. This works fine but I lose the automatic ability which I coded to change the navigation drawer to show the back arrow if the stack is greater than 1.

I tried removing the entire stack and adding the individual fragments in the order the user clicks when the device is rotated. This doesn't work well. Seems remove and replace are out of wack.

I tried adding the fragment back using fragmentManager.findbytag but it throws an illegal state exception "fragment already added". I found a solution on SO to remove the transition. Worked once then stopped. No idea why.

I put in a toast to check show the backstack count each time it changes, and I realized that the stack still shows the correct count after the addition but the page is still blank. It even requires 2 backpresses to exit the activity to the previous activity.

I put a breakpoint to check if onCreateView is called in the fragment and yes, it is called each time the phone is rotated.

Basically, my code now looks like this since I have given up.

@Override
    protected void onCreate(Bundle savedInstanceState) {
        mPosition = 1;

        super.onCreate(savedInstanceState);

        if(savedInstanceState != null) {
            mLastArtistFragmentTag = savedInstanceState.getString(SAVE_FRAGMENT_LAST_ARTIST);
            mLastAlbumFragmentTag = savedInstanceState.getString(SAVE_FRAGMENT_LAST_ALBUM);
            mLastSongFragmentTag = savedInstanceState.getString(SAVE_FRAGMENT_LAST_SONG);

            mLastFragmentType = savedInstanceState.getInt(SAVE_FRAGMENT_LAST_TYPE);
        }

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                Load();
            }
        }, 100);
    }

    void Load() {

        findViewById(R.id.loading).setVisibility(View.GONE);

        ViewStub stub = (ViewStub) findViewById(R.id.container_stub);
        stub.setLayoutResource(R.layout.activity_music);
        stub.inflate();




    if(mLastArtistFragmentTag == null) {
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.base_container, new Artists(), FRAGMENT_TAG_BASE)


                   .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
                    .commit();
        }
            else {
                getSupportFragmentManager().beginTransaction()
                        .replace(R.id.base_container, new Artists(), FRAGMENT_TAG_BASE)
                    //.add(R.id.base_container, Albums.newInstance(mLastArtistFragmentTag), mLastArtistFragmentTag)
//.add(R.id.base_container, getSupportFragmentManager().findFragmentByTag(mLastArtistFragmentTag), mLastArtistFragmentTag)
                    //.addToBackStack(mLastArtistFragmentTag)
                .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
                .commit();
        }

    }

@Override
    public void onSaveInstanceState(Bundle instanceState) {
        super.onSaveInstanceState(instanceState);

        if(mLastFragmentType != -1) {
            instanceState.putString(SAVE_FRAGMENT_LAST_ARTIST, mLastArtistFragmentTag);
            instanceState.putString(SAVE_FRAGMENT_LAST_ALBUM, mLastAlbumFragmentTag);
            instanceState.putString(SAVE_FRAGMENT_LAST_SONG, mLastSongFragmentTag);

            instanceState.putInt(SAVE_FRAGMENT_LAST_TYPE, mLastFragmentType);
        }

    }

Fragment Code is like this

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

    final ListView listView = (ListView) inflater.inflate(R.layout.fragment_albums, container, false);
    listView.addHeaderView(inflater.inflate(R.layout.header_artist_info, null));

    try {
        String uri2 = "http://someurl";
        NetworkRequest.FetchJSON(Request.Method.GET, uri2, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                try {
                    JSONArray songs = response.getJSONArray("songs");
                    //HashMap<String, Song> recentSongs = new HashMap<String, Song>();
                    ArrayList<Song> latest = new ArrayList<Song>();

                    for (int i = 0; i < songs.length(); i++) {
                        Song s = new Song(songs.getJSONObject(i));
                        latest.add(s);
                    }

                    AlbumListAdapter pgiAdapter = new AlbumListAdapter(getActivity(), latest);
                    SwingBottomInAnimationAdapter swingBottomInAnimationAdapter = new SwingBottomInAnimationAdapter(pgiAdapter);

                    swingBottomInAnimationAdapter.setAbsListView(listView);
                    listView.setAdapter(swingBottomInAnimationAdapter);

                } catch (JSONException ex) {
                    Toast.makeText(getActivity(), ex.getMessage(), Toast.LENGTH_LONG).show();
                }
            }
        });
    } catch (Exception ex) {
        Toast.makeText(getActivity(), ex.getMessage(), Toast.LENGTH_LONG).show();
    }

    return listView;
}

before you ask, yes I did move the Load method to inside the onCreate method. Still did not work.

I am really stuck here and need your help. Please help me. Thanks.

frostymarvelous
  • 2,786
  • 32
  • 43

2 Answers2

5

Depending on how you recreate the activity you may need to manually handle fragment state changes. In the worst of cases you may need to detach and reattach the fragment to force view recreation.

public void onConfigurationChanged(Configuration newConfig) {
  super.onConfigurationChanged(newConfig);
  FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
  transaction.detach(activeFrag).attach(activeFrag).commit();
}

and have the correct hook on your AndroidManifest.xml

android:configChanges="orientation|screenSize"
MLProgrammer-CiM
  • 17,231
  • 5
  • 42
  • 75
1

Thanks to @MLProgrammer-CiM I found a fix to this issue.

if(mLastArtistFragmentTag == null) {
    getSupportFragmentManager().beginTransaction()
            .replace(R.id.base_container, new Artists(), FRAGMENT_TAG_BASE)
            .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
            .commit();
} else {
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();

    Fragment base = getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG_BASE);
    Fragment art = getSupportFragmentManager().findFragmentByTag(mLastArtistFragmentTag);

    ft.detach(base).attach(base).detach(art).attach(art).commit();
}

I guess I have to do this for all items in the backstack. Glad at least it works. Finally!

dustinrwh
  • 888
  • 1
  • 14
  • 16
frostymarvelous
  • 2,786
  • 32
  • 43
  • I noticed some activity recently on this. Due to the issues with fragments, I moved away completely and built a library to help me with this. It can be found at https://github.com/frostymarvelous/Folio – frostymarvelous Oct 07 '16 at 11:10