I am working with fragments and pushing new fragments on the backstack but when I rotate the device twice the fragment's onCreateView
, onActivityCreated
, and so on in the fragment life cycle methods are never called leaving a blank screen. This only occurs when a fragment has been added to the backstack or returning to the first fragment in the backstack.
Here is my activity's fragment handling methods:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Injection
MormonChannel.injectActivity(this);
setDrawerIndicatorEnabled(true);
// Do not set currentNavigationItem here.
NavigationItemSelectedEvent.NavigationItem navItem = null;
Intent intent = getIntent();
if (intent != null) {
navItem = (NavigationItemSelectedEvent.NavigationItem)
intent.getSerializableExtra(EXTRA_NAV_ITEM);
}
if (savedInstanceState == null) {
FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction().replace(R.id.container, new FeatureListFragment()).commit();
if (navItem != null) {
onNavigationItemSelected(new NavigationItemSelectedEvent(navItem));
} else {
currentNavigationItem = NavigationItemSelectedEvent.NavigationItem.FEATURES;
}
}
}
@Subscribe
public void onNavigationItemSelected(NavigationItemSelectedEvent event) {
if (currentNavigationItem == event.getNavigationItem()) {
return;
}
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.popBackStack();
NavigationItemSelectedEvent.NavigationItem navigationItem = event.getNavigationItem();
String name = navigationItem.getName();
switch (navigationItem) {
default:
case FEATURES:
// Nothing needs to be done it is already there.
break;
case AUDIO:
fragmentManager.beginTransaction().replace(R.id.container,
CollectionListFragment.newInstance(prefs.getLanguageId(), prefs.getAudioCollectionId()))
.addToBackStack
(name).commit();
break;
case VIDEO:
fragmentManager.beginTransaction().replace(R.id.container,
CollectionListFragment.newInstance(prefs.getLanguageId(), prefs.getVideoCollectionId()))
.addToBackStack(name).commit();
break;
case RADIO:
fragmentManager.beginTransaction().replace(R.id.container,
CollectionListFragment.newInstance(prefs.getLanguageId(), prefs.getRadioCollectionId()))
.addToBackStack(name).commit();
break;
case HISTORY:
fragmentManager.beginTransaction().replace(R.id.container, new HistoryFragment()).addToBackStack(name).commit();
break;
case DOWNLOADS:
fragmentManager.beginTransaction().replace(R.id.container, new DownloadsFragment()).addToBackStack(name).commit();
break;
case PLAYLISTS:
fragmentManager.beginTransaction().replace(R.id.container, new PlaylistFragment()).addToBackStack(name).commit();
break;
}
currentNavigationItem = navigationItem;
}
Here is my CollectionListFragment Code:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MormonChannel.injectFragment(this);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.collection_list_fragment, container, false);
ButterKnife.inject(this, v);
return v;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
listView.setDividerHeight(0);
listView.setFastScrollEnabled(true);
Bundle args = getArguments();
if (args != null) {
languageId = args.getLong(ARG_LANGUAGE_ID, -1L);
collectionId = args.getLong(ARG_COLLECTION_ID, -1L);
if (args.containsKey(ARG_SORT)) {
sort = (Sort) args.getSerializable(ARG_SORT);
}
}
if (collectionId == -1L || languageId == -1L) {
// TODO Implement Empty Collection Text
} else {
collection = collectionManager.findByCollectionId(languageId, collectionId);
getLoaderManager().initLoader(LOADER_ID, null, this);
}
titleEvent = new TitleChangeEvent(collection != null ? collection.getTitle() : getString(R.string.app_name));
bus.post(titleEvent);
}
Manifest for activity:
<activity
android:name=".activity.MainActivity"
android:launchMode="singleTask">
<meta-data
android:name="android.app.default_searchable"
android:value=".activity.SearchActivity"/>
</activity>
The onCreate() is called first, for doing any non-graphical initialisations. Next, you can assign and declare any View variables you want to use in onCreateView() . Afterwards, use onActivityCreated() to do any final initialisations you want to do once everything has completed.
onCreate() is called to do initial creation of the fragment. onCreateView() is called by Android once the Fragment should inflate a view. onViewCreated() is called after onCreateView() and ensures that the fragment's root view is non-null .
onCreate is called on initial creation of the fragment. You do your non graphical initializations here. It finishes even before the layout is inflated and the fragment is visible. onCreateView is called to inflate the layout of the fragment i.e graphical initialization usually takes place here.
The onActivityCreated() method is called after onCreateView() and before onViewStateRestored() . onDestroyView() : Called when the View previously created by onCreateView() has been detached from the Fragment . This call can occur if the host Activity has stopped, or the Activity has removed the Fragment .
In your CollectionListFragment Code, add call to setRetainInstance() method in the onCreate() method, with true as its argument:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
MormonChannel.injectFragment(this);
}
Using setRetainInstance(true) ensures that when configuration changes occur activity will be killed but android will not destroy the fragment it is hosting.
Instead android will save the fragment state and detach the fragment from the activity. Also it wont destroy the fragment and so it wont create it later when hosting activity is created. So fragment will not receive calls to its onDestroy() and onCreate() methods.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With