奇怪的onPause(),onResume()的片段行为 [英] Strange onPause(), onResume() behaviour in fragments

查看:169
本文介绍了奇怪的onPause(),onResume()的片段行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

应用程序有一个主要活动(MainActivity.java)有三个选项卡(片段)。我可以使用左轻扫(riht)或点击一个特定的标签上它们之间进行浏览。

在开始应​​用,第1片段被示出。

如果我去从第1段第2个片断,然后回到第一片段,没有任何反应(onResume()的1RD片段不叫),所以它不会刷新它的内容。

如果我去从第1段第3个片段,然后直接回到第一片段,创建片段1的onCreateView()和它的onR​​esume()被调用,这是正确的。

如果我从第三片段转到第二片段,所述onCreateView()和onResume()的片段1是所谓的,但不是onCreateView fragment2的

我猜MainActivity逻辑是不对的,所以我会恳请有人来看看,并告诉我可能是错的。

MainActivity.java:

 公共类MainActivity扩展FragmentActivity实现ActionBar.TabListener {CollectionPagerAdapter mCollectionPagerAdapter;
公共TTSocket插座;
DBHandler分贝;
公共字符串logged_user;
私人LogedinPerson人;
ViewPager mViewPager;公共无效的onCreate(捆绑savedInstanceState){
    super.onCreate(savedInstanceState);    的setContentView(R.layout.main);    捆绑额外= getIntent()getExtras()。
    logged_user = extras.getString(logged_user);
    插座= TTSocket.getInstance();
    socket.currentRef =这一点;    DB =新DBHandler(本);
    人= db.getLogedInPerson();    socket.dbHandler = DB;
    socket.person =人;    如果(!socket.isInit){
        字符串typeInitStr ={\\类型\\:\\初始化\\,\\用户ID \\:\\+ person.getUserId()+\\};
        socket.Send(typeInitStr);
    }
    mCollectionPagerAdapter =新CollectionPagerAdapter(getSupportFragmentManager());    //设置操作栏。
    最后的动作条动作条= getActionBar();    //指定我们将在行动酒吧显示标签。
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);    //设置的ViewPager,连接适配器,并设立一个监听器
    //用于当
    //用户部分之间刷卡。
    mViewPager =(ViewPager)findViewById(R.id.pager);
    mViewPager.setAdapter(mCollectionPagerAdapter);
    mViewPager.setOnPageChangeListener(新ViewPager.SimpleOnPageChangeListener(){
            @覆盖
            公共无效使用onPageSelected(INT位置){
            Log.d(TEST位置+);
            //相应的标签。
            //我们也可以使用ActionBar.Tab#选择()如果要做到这一点
            //我们必须在标签的参考
            actionBar.setSelectedNavigationItem(位置);
            }
        });    //对于每一个应用中的部分,添加标签,操作栏。
    的for(int i = 0; I< mCollectionPagerAdapter.getCount();我++){
        //创建对应于定义的页面标题文字标签
        //适配器。
        //还可以指定这个活动对象,它实现了
        // TabListener接口,作为
        //侦听器时选择此选项卡。
        如果(我== 0){
            actionBar.addTab(actionBar.newTab()
                    .setIcon(R.drawable.messages)
                    .setTabListener(本));        }否则如果(ⅰ== 1){
            actionBar.addTab(actionBar.newTab()
                    .setIcon(R.drawable.contacts)
                    .setTabListener(本));
        }其他{
            actionBar.addTab(actionBar.newTab()
                    .setIcon(R.drawable.history)
                    .setTabListener(本));
        }
    }
}@覆盖
保护无效onResume(){
    // TODO自动生成方法存根
    super.onResume();    socket.currentRef =这一点;
    socket.dbHandler = DB;
    socket.person =人;    //mCollectionPagerAdapter.notifyDataSetChanged();
}公共无效onTabUnselected(ActionBar.Tab选项卡,FragmentTransaction fragmentTransaction){
}公共无效onTabSelected(ActionBar.Tab选项卡,FragmentTransaction fragmentTransaction){
//当选择给定的标签上,切换到相应的页面
//的ViewPager。
mViewPager.setCurrentItem(tab.getPosition());
}公共无效onTabReselected(ActionBar.Tab选项卡,FragmentTransaction fragmentTransaction){
}/ **
 * A {@link FragmentPagerAdapter}返回对应片段
 *应用程序的主要部分之一。
 * /
公共类CollectionPagerAdapter扩展FragmentPagerAdapter {最终诠释NUM_ITEMS = 3; //标签的数公共CollectionPagerAdapter(FragmentManager FM){
    超(FM);
}
/ *
@覆盖
公共片段的getItem(int i)以{
    片段片段=新TabFragment();
    捆绑ARGS =新包();
    args.putInt(TabFragment.ARG_OBJECT,I);
    fragment.setArguments(参数);
    返回片段;
}
* /
@覆盖
公共片段的getItem(INT位置){    片段片段=新的片断();
    捆绑ARGS =新包();
    args.putInt(TabFragment.ARG_OBJECT,位置);
    开关(位置){
        情况下0:
            Log.i(碎片,0);
            片段=新Tab1Fragment();
            fragment.setArguments(参数);
            返回片段;
        情况1:
            Log.i(碎片,1);
            片段=新Tab2Fragment();
            fragment.setArguments(参数);
            返回片段;
        案例2:
            Log.i(碎片,2);
            片段=新Tab3Fragment();
            fragment.setArguments(参数);
            返回片段;
        默认:
            打破;
    }    返回片段;
}@覆盖
公众诠释的getCount(){
    返回NUM_ITEMS;
}@覆盖
公共CharSequence的getPageTitle(INT位置){
    字符串tabLabel = NULL;
    开关(位置){
    情况下0:
    tabLabel =的getString(R.string.label1);
    打破;
    情况1:
    tabLabel =的getString(R.string.label2);
    打破;
    案例2:
    tabLabel =的getString(R.string.label3);
    打破;
    }    返回tabLabel;
}
}/ **
 *用于启动演示应用程序的其他部分片段。
 * /
公共静态类TabFragment扩展片段{公共静态最后弦乐ARG_OBJECT =对象;@覆盖
公共查看onCreateView(LayoutInflater充气器,容器的ViewGroup,
    捆绑savedInstanceState){    捆绑ARGS = getArguments();
    INT位置= args.getInt(ARG_OBJECT);    INT tabLayout = 0;
    开关(位置){
    情况下0:
        tabLayout = R.layout.tab1;
        打破;
    情况1:
        tabLayout = R.layout.tab2;
        打破;
    案例2:
        tabLayout = R.layout.tab3;
        打破;
    }    查看rootView = inflater.inflate(tabLayout,集装箱,FALSE);    返回rootView;
}
}
}


解决方案

  

奇怪的onPause()onResume()在片段的行为()


这不是奇怪的行为,但ActionSherlock本土的行为。这种行为被用于缓存 - > optimalisation对旧设备以较低的 RAM 这也是为什么片段缓存

如果您需要更新片段的内容并不试图取代它的布局或类似的东西。如果你想在页面之间滚动时更新片段,你需要使用FragmentPagerAdapter的方法:

  @覆盖
公众诠释getItemPosition(Object对象){
   //执行
   返回super.getItemPosition(对象);
}

此方法被调用时,你会调用

  notifyDataSetChanged();

您FragmentPagerAdapter。它是让你的片段更新方便的方法。还有更多的方法如何做到这一点,但在这里,我会告诉你我是如何做的。

让您的片段实现例如接口被称为更新的:

 界面更新的{
   公共无效更新();
}公共类MyFragment扩展SherlockFragment实现可更新的{   @覆盖
   公共无效更新(){
      //执行片段更新
   }
}

而在这个方法中,你将执行更新。现在回到 getItemPosition()方法。该方法将用于从片段调用更新()方法即:

  @覆盖
   公众诠释getItemPosition(Object对象){
      片段F =(片段)对象;
      //确定哪些片段
      如果(F的instanceof MyFragment){
         ((MyFragment)F).update(); //调用update()方法
      }      返回super.getItemPosition(对象);
   }

现在,只要您滚动页面还是有些标签上点击(你还需要调用 notifyDataSetChanged()),你能够做出片段更新。这样,反对破坏并重新创建片段(S)每次滚动的时间或点击选项卡更有效率。但如何我说这是不是唯一的解决办法有更多的可能的解决方案。


注意: getItemPosition()可以返回两个值: POSITION_NONE 海泡石。两者之间的区别在于,第一个指示碎片将永远破坏并重新创建,是不是很有效,第二表明碎片将不会改变(是在正确的地方)。

有关更详细的解释看这里

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;
}
}


}

解决方案

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.

这篇关于奇怪的onPause(),onResume()的片段行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆