Strange onPause(), onResume() behaviour in fragments

蓝咒 提交于 2019-12-23 03:23:06

问题


The application has a main activity (MainActivity.java) with three tabs (fragments). I can navigate between them using the swipe left (riht) or clicking on a specific tab.

Upon starting the application, the 1st fragment is shown.

If I go to the 2nd fragment from the 1st fragment and then back to the 1st fragment, nothing happens (onResume() of the 1rd fragment isn't called), so it doesn't refresh it's content.

If I go to the 3rd fragment from the 1st fragment and then directly back to the 1st fragment, the onCreateView() of fragment1 is created and it's onResume() is called, which is correct.

If I go from the 3rd fragment to the 2nd fragment, the onCreateView() and onResume() of fragment1 are called, but not the onCreateView of fragment2.

I guess the logic in MainActivity isn't right, so I would kindly ask someone to take a look and tell me what could be wrong.

MainActivity.java:

public class MainActivity extends FragmentActivity implements ActionBar.TabListener {

CollectionPagerAdapter mCollectionPagerAdapter;
public TTSocket socket;
DBHandler db;
public String logged_user;
private LogedinPerson person;
ViewPager mViewPager;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    Bundle extras = getIntent().getExtras();
    logged_user = extras.getString("logged_user");
    socket = TTSocket.getInstance();
    socket.currentRef = this;

    db = new DBHandler(this);
    person=db.getLogedInPerson();

    socket.dbHandler=db;
    socket.person=person;

    if(!socket.isInit){
        String typeInitStr = "{\"Type\":\"Init\", \"UserId\":\""+ person.getUserId() +"\"}";
        socket.Send(typeInitStr);
    }


    mCollectionPagerAdapter = new CollectionPagerAdapter(getSupportFragmentManager());

    // Set up action bar.
    final ActionBar actionBar = getActionBar();

    // Specify that we will be displaying tabs in the action bar.
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    // Set up the ViewPager, attaching the adapter and setting up a listener
    // for when the
    // user swipes between sections.
    mViewPager = (ViewPager) findViewById(R.id.pager);
    mViewPager.setAdapter(mCollectionPagerAdapter);
    mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
            Log.d("TEST",position+"");
            // the corresponding tab.
            // We can also use ActionBar.Tab#select() to do this if
            // we have a reference to the Tab
            actionBar.setSelectedNavigationItem(position);
            }
        });

    // For each of the sections in the app, add a tab to the action bar.
    for (int i = 0; i < mCollectionPagerAdapter.getCount(); i++) {
        // Create a tab with text corresponding to the page title defined by
        // the adapter.
        // Also specify this Activity object, which implements the
        // TabListener interface, as the
        // listener for when this tab is selected.
        if(i == 0){
            actionBar.addTab(actionBar.newTab()
                    .setIcon(R.drawable.messages)
                    .setTabListener(this));

        }else if(i == 1){
            actionBar.addTab(actionBar.newTab()
                    .setIcon(R.drawable.contacts)
                    .setTabListener(this));
        }else{
            actionBar.addTab(actionBar.newTab()
                    .setIcon(R.drawable.history)
                    .setTabListener(this));
        }
    }
}

@Override
protected void onResume() {
    // TODO Auto-generated method stub
    super.onResume();

    socket.currentRef = this;
    socket.dbHandler=db;
    socket.person=person;

    //mCollectionPagerAdapter.notifyDataSetChanged();
}

public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}

public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}

public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}

/**
 * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
 * one of the primary sections of the app.
 */
public class CollectionPagerAdapter extends FragmentPagerAdapter {

final int NUM_ITEMS = 3; // number of tabs

public CollectionPagerAdapter(FragmentManager fm) {
    super(fm);
}
/*
@Override
public Fragment getItem(int i) {
    Fragment fragment = new TabFragment();
    Bundle args = new Bundle();
    args.putInt(TabFragment.ARG_OBJECT, i);
    fragment.setArguments(args);
    return fragment;
}
*/
@Override  
public Fragment getItem(int position) {  

    Fragment fragment = new Fragment(); 
    Bundle args = new Bundle();
    args.putInt(TabFragment.ARG_OBJECT, position);
    switch (position) {  
        case 0:  
            Log.i("Fragment", "0");
            fragment =  new Tab1Fragment();
            fragment.setArguments(args);
            return fragment; 
        case 1:  
            Log.i("Fragment", "1");
            fragment =  new Tab2Fragment();  
            fragment.setArguments(args);
            return fragment; 
        case 2:  
            Log.i("Fragment", "2");
            fragment =  new Tab3Fragment();   
            fragment.setArguments(args);
            return fragment;  
        default:  
            break;  
    }

    return fragment;
}

@Override
public int getCount() {
    return NUM_ITEMS;
}

@Override
public CharSequence getPageTitle(int position) {
    String tabLabel = null;
    switch (position) {
    case 0:
    tabLabel = getString(R.string.label1);
    break;
    case 1:
    tabLabel = getString(R.string.label2);
    break;
    case 2:
    tabLabel = getString(R.string.label3);
    break;
    }

    return tabLabel;
}
}

/**
 * A fragment that launches other parts of the demo application.
 */
public static class TabFragment extends Fragment {

public static final String ARG_OBJECT = "object";

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

    Bundle args = getArguments();
    int position = args.getInt(ARG_OBJECT);

    int tabLayout = 0;
    switch (position) {
    case 0:
        tabLayout = R.layout.tab1;
        break;
    case 1:
        tabLayout = R.layout.tab2;
        break;
    case 2:
        tabLayout = R.layout.tab3;
        break;
    }

    View rootView = inflater.inflate(tabLayout, container, false);

    return rootView;
}
}


}

回答1:


Strange onPause(), onResume() behaviour() in fragments

It's not strange behaviour but native behaviour of ActionSherlock. This kind of behaviour is used for caching -> optimalisation for older devices with lower RAM this is reason why fragments are cached.

If you need to update content of fragment don't try to replace its layout or something similar. If you want to update fragment when scrolling between pages, you need to use method of FragmentPagerAdapter:

@Override
public int getItemPosition(Object object) {
   // implementation
   return super.getItemPosition(object);
}

This method is called when you will call

notifyDataSetChanged();

on your FragmentPagerAdapter. It's handy method for make updates of your fragments. There are more ways how to do it but here i'll show you how I'm doing it.

Let your fragments implement interface for example called Updateable:

interface Updateable {
   public void update();
}

public class MyFragment extends SherlockFragment implements Updateable {

   @Override
   public void update() {
      // perform Fragment updates
   }
}

And in this method you will perform updates. Now back to getItemPosition() method. This method will be used for invoking update() method from Fragment i.e:

@Override
   public int getItemPosition(Object object) {
      Fragment f = (Fragment) object;
      // determine which fragment
      if (f instanceof MyFragment) {
         ((MyFragment) f).update(); // invokes update() method
      }

      return super.getItemPosition(object);
   }

Now whenever you scroll page or tap on some tab (you need also call notifyDataSetChanged()) you are able to make Fragment updates. This way is more efficient against destroying and recreating fragment(s) each time you scrolling or clicking on tabs. But how i said this is not only solution there are more possible solutions.


Note: getItemPosition() can return two values: POSITION_NONE and UNCHANGED. Difference between both is that first indicates that Fragment will be always destroyed and recreated that is not very efficient and second indicates that Fragment won't be changed (is in on right place).

For more detailed explanation look here.




回答2:


That is because ViewPager doesn't hide all fragments you switch. You can control this behaviour by setOffscreenPageLimit



来源:https://stackoverflow.com/questions/18762956/strange-onpause-onresume-behaviour-in-fragments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!