Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dealing with fragment and view pager : can't change tag of fragment AND Recursive entry to executePendingTransactions

Firstly, I know these subjects have been created a lot of time on stackoverflow, but I don't have found the solution to my problems. Secondly, I'm french, so my english is not perfect, sorry per advance and tell me if you don't understand something. And to finish this introduction, it's the first time that I'm dealing with fragments, so, sorry if there is something that I don't have well understand !

I have three buttons, that allow to switch between three fragments. Inside one of these fragments, I have a view pager with two fragments. For the moment, each fragments (there are 5), only contains a TextView. I'm using the latest version of android-support-v4 (I have read a lot of subject in stackoverflow that say that the latest version of support solve the "Recursive entry to executePendingTransactions" error that I have).

My two problems :

  • When I click two times in one button, I have an IllegaleStateException "can't change tag of fragment". I was able to fix that by creating a new fragment on onButtonSelected method, but I don't want to recreate fragment each time, for memory reasons and for functional reasons : fragment have to keep her state. This problem is not my main problem, indeed, i know that to disable the button when user is already on fragment is possible, but it's strange to have an exception when this management is not done, no ?.

  • When I go out from the fragment with the view pager, and I go back to this fragment, I have an IllegalStateException "Recursive entry to executePendingTransactions". I can fix this by setting my adapter on an handler, or use FragmentStatePagerAdapter instead of FragmentPageAdapter (see Display fragment viewpager within a fragment), but even if my application don't crash, when I go back to my fragment with the view pager, the view pager has disapear !

Can you help me ?

Java source code is bellow, layout source code is, I think, useless.

MainActivity :

public class MainActivity extends SherlockFragmentActivity{

private SherlockFragment fragmentOne, fragmentTwo, fragmentThree;

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

//      this.fragmentOne = new fragmentOne();
//      this.fragmentTwo = new fragmentTwo();
//      this.fragmentThree = new fragmentThree();
// Call new or instanciate ? What's the correct way ?

    this.fragmentOne = (SherlockFragment) SherlockFragment.instantiate(this, FragmentOne.class.getName());
    this.fragmentTwo = (SherlockFragment) SherlockFragment.instantiate(this, FragmentTwo.class.getName());
    this.fragmentThree = (SherlockFragment) SherlockFragment.instantiate(this, FragmentThree.class.getName());

    // Add fragment
    FragmentTransaction transaction = (
        this.getSupportFragmentManager().beginTransaction()
    );      
    transaction.add(
        R.id.tab_fragment,
        this.fragmentOne,
        this.fragmentOne.toString()
    );
    transaction.commit();

}

public void onButtonSelected(View v){

    switch (v.getId()){

        case R.id.button_one_tab:{
            showFragment(this.fragmentThree);
            break;
        }
        case R.id.button_two_tab:{
            showFragment(this.fragmentOne);
            break;
        }
        case R.id.button_three_tab:{
            showFragment(this.fragmentTwo);
            break;
        }
        default:{
            break;
        }

    }

}

public void showFragment(SherlockFragment fragmentToShow){

    FragmentTransaction transaction = (
        this.getSupportFragmentManager().beginTransaction()
    );

    transaction.replace(R.id.tab_fragment, fragmentToShow, fragmentToShow.toString());
    transaction.commit();

}

}

Fragment two and three only inflate a layout that only contains a TextView. Fragment one (note that i'm using a DirectionalViewPager - a lib - instead of a ViewPager):

public class FragmentOne extends SherlockFragment{

private FragmentOneAdapter fragmentOneAdapter;

@Override
public void onActivityCreated(Bundle savedInstanceState) {

    super.onActivityCreated(savedInstanceState);

    // Set up the pager
    final DirectionalViewPager pager = (DirectionalViewPager)getActivity().findViewById(R.id.pager);
    if (this.fragmentOneAdapter== null){
        this.fragmentOneAdapter= new FragmentOneAdapter (getActivity().getSupportFragmentManager());
    }
    pager.setAdapter(fragmentOneAdapter);

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment_landing_page, container, false);
}

FragmentOneAdapter :

public class FragmentOneAdapter extends FragmentPagerAdapter{

private ArrayList<SherlockFragment> fragmentsList;

public FragmentOneAdapter(FragmentManager fragmentManager) {

    super(fragmentManager);

    SherlockFragment fragmentFour = new FragmentFour();
    SherlockFragment fragmentFive = new FragmentFive();

    this.fragmentsList = new ArrayList<SherlockFragment>();
    this.fragmentsList.add(fragmentFour);
    this.fragmentsList.add(fragmentFive);

}

@Override
public Fragment getItem(int position) {
    return this.fragmentsList.get(position);
}

@Override
public int getCount() {
    return this.fragmentsList.size();
}

}

Thanks per advance for your help !

like image 494
Sébastien BATEZAT Avatar asked Oct 21 '22 16:10

Sébastien BATEZAT


1 Answers

I have solved my problem !

I have simply replace getSupportFragmentManager() on FragmentOne to getChildFragmentManager(). Then, I have edited my onButtonSelected's method by creating a new instance of fragment each time instead of using my three different instances (if I don't do that, I have an exception : java.lang.IllegalStateException: Activity has been destroyed).

I have still a problem with this solution : I lose the state of each fragment each time I'm switching between fragmentOne, fragmentTwo and fragmentThree. Do you have a solution for that ?

like image 74
Sébastien BATEZAT Avatar answered Oct 27 '22 09:10

Sébastien BATEZAT