Handling fragment states

Working with fragments is one of the most difficult tasks of android development. Handling configuration changes in fragment is a task you would be really glad on accomplishing.

Background check: I am working on a Udacity certification project. It has tabs and lots of fragments to handle cases for tablets. Handling orientation changes for fragments was a frustrating task not because it is very difficult but just because you have to understand some basics of fragments and android lifecycles.


So here are some tips for handling config changes in fragments:

1.)Most of the problems come because android recreates the whole fragment again on config changes.

First thing you should look is whether you are reusing the old fragment or not. If not,do it. Set a tag while replacing fragments and use it to find old fragment and use that only.

final Fragment fragmentByTag = getSupportFragmentManager().findFragmentByTag(tag);
if (fragmentByTag == null) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.frag_container, new TabsLayoutFragment(), tag).commit();
} else {
getSupportFragmentManager().beginTransaction()
.replace(R.id.frag_container_posts, fragmentByTag, tag).commit();
}
2.)When using TabLayout, better to use FragmentStatePagerAdapter instead on FragmentPagerAdapter or simply PagerAdapter.

You can even use SmartFragmentPagerAdapter for getting fragments from adapter in a better way for complex tasks.

3.) For RecyclerView , use this link handle scroll. You can have the advantage of LayoutManager’s these methods.
LayoutManager.onSaveInstanceState()
LayoutManager.onRestoreInstanceState(Parcelable state);

Personally for me, saving both first visible position and layoutmanager state worked. I don’t know why simply adding only 1 of these doesn’t works for me.

By the way, I saved first visible as:

if (layoutManager instanceof LinearLayoutManager)
outState.putInt(POSITION_KEY, ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition());
//If staggeredGridLayoutManager we need the minimum of first of all //the columns. For me columns/span is 2.
else if (layoutManager instanceof StaggeredGridLayoutManager) {
int spanPositions[] = new int[2];
spanPositions = ((StaggeredGridLayoutManager) layoutManager).findFirstVisibleItemPositions(spanPositions);
final int min = Math.min(Math.max(0, spanPositions[0]), Math.max(0, spanPositions[1]));
outState.putInt(POSITION_KEY + "_" + type, min);
}

Ending Note: It might be a little tricky with fragments but it works in the end. You just have to be little careful.

PS: Better avoid setRetainInstance(true) in normal fragments.