I recently switched my app from native fragments to the v4 support fragment library but now when I pop the fragment off the back stack onCreateView() is not called on the previous fragment. I need to be able to change the buttons in my header when the fragment is replaced. I've tried to use both onHiddenChanged() and setUserVisibleHint() but neither seemed to be called when the fragment is coming back into view.
Reading another thread, I see people say to use onBackStateChanged listener but I'm having a few problems with it. When my app starts up, it replaces a fragment container with a list view of articles (section). When a user selects an article, it replaces the section fragment with the article fragment. Logging the count of the back stack is now 1. When the user hits the back button, the section view is shown again. I want to be able to call onResume for my section fragment but the count is 0 and says:
09-28 00:45:17.443 21592-21592/com.reportermag.reporter E/Backstack size﹕ 0 java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.app.Fragment.onResume()' on a null object reference
How do I get a reference to the article list fragment so that I can call onResume()?
Code I've tried:
public void onBackStackChanged() {
android.support.v4.app.FragmentManager manager = getSupportFragmentManager();
if (manager != null)
{
int backStackEntryCount = manager.getBackStackEntryCount();
Log.e("Backstack size", Integer.toString(backStackEntryCount));
android.support.v4.app.Fragment fragment = manager.getFragments().get(backStackEntryCount > 0 ? backStackEntryCount-1:backStackEntryCount);
fragment.onResume();
}
}
public void setUserVisibleHint(boolean visible)
{
super.setUserVisibleHint(visible);
if (visible && isResumed())
{
// Set the titlebar
Titlebar.setColor(getResources().getColor(R.color.graydark));
Titlebar.setVisible(Titlebar.VIEWS.MENU, Titlebar.VIEWS.LOGO, Titlebar.VIEWS.SEARCH);
// Clear Search
SearchFragment.clearSearch();
}
}
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if(hidden == false) {
// Set the titlebar
Titlebar.setColor(getResources().getColor(R.color.graydark));
Titlebar.setVisible(Titlebar.VIEWS.MENU, Titlebar.VIEWS.LOGO, Titlebar.VIEWS.SEARCH);
// Clear Search
SearchFragment.clearSearch();
}
}
Update:
Here is my fragment loaders:
public void loadSectionFragment(Integer sectionID) {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Set the arguments
Bundle bundle = new Bundle();
bundle.putInt("section", sectionID);
// Add the section fragment
Fragment sectionFrag = sections.get(sectionID);
if (sectionFrag == null) {
sectionFrag = new SectionFragment();
sectionFrag.setArguments(bundle);
sections.put(sectionID, sectionFrag);
}
transaction.setCustomAnimations(R.animator.enter_anim, R.animator.exit_anim);
transaction.replace(R.id.fragment_container, sectionFrag);
transaction.addToBackStack(null);
// Commit the new fragment
transaction.commit();
}
public void loadArticleFragment() {
FragmentTransaction transaction = activity.getSupportFragmentManager().beginTransaction();
// Set the arguments
Bundle bundle = new Bundle();
bundle.putInt("id", id);
bundle.putInt("color", color);
// Add the article fragment
Fragment articleFrag = new ArticleFragment();
articleFrag.setArguments(bundle);
transaction.replace(R.id.fragment_container, articleFrag);
transaction.addToBackStack(null);
// Commit the new fragment
transaction.commit();
}
If you whant update your fragment when you back from backstack use this pattern:
backStackListener = new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
Fragment f = getSupportFragmentManager().findFragmentById(R.id.yourFragmentContainerId);
if(f!=null){
if(f instanceof YourSectionFragment ){
((YourSectionFragment )f).update();
}else{
}
}
}
};
getSupportFragmentManager().addOnBackStackChangedListener(backStackListener);
Then add method to your fragment
public void update(){
//update your ui
}