FragmentStatePagerAdapter onPageSelected事件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FragmentStatePagerAdapter onPageSelected事件相关的知识,希望对你有一定的参考价值。

我有一个FragmentStatePagerAdapter,里面有6个片段。

每个Fragment连接到服务器并加载数据。

现在,服务器连接正在Fragment.onStart()中完成,这意味着在任何时候,我都有3个http请求(选定的片段,每侧一个)。

我想要的是当时只有一个连接,所以我打算使用

 viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener()
 { 
    @Override
    public void onPageSelected(final int position)
    {
        CustomFragment fragment = (CustomFragment) myFragmentStatePagerAdapter.getItem(position);

        fragment.onSelected();//do stuff in here
    }
 });

问题是,getItem()返回片段的新实例,尚未添加到管理器中(因此,尚未创建视图等)。

此外,我已经尝试过setUserVisibleHint(boolean isVisibleToUser)但是没有被调用可见,仅在isVisibleToUser = false

那么,如何为Fragment实现“onPageSelected()”事件呢?

提前致谢

答案

对你来说最好的解决方案是覆盖setUserVisibleHint()。确保你扩展FragmentPagerAdapter。从它的source code你可以看到它也称为setUserVisibleHint(true)可见碎片。我一直使用它,效果很好。

// adapter
public static class PlayerAdapter extends FragmentStatePagerAdapter {
    public PlayerAdapter(FragmentManager fm) {
        super(fm);
    }

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

    @Override
    public Fragment getItem(int position) {
        return new SimpleFragment();
    }
}

// fragment
public class SimpleFragment extends Fragment {

    private static final String TAG = BookControlsFragment.class.getSimpleName();

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

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        Log.d(TAG, "setUserVisibleHint: " + isVisibleToUser);
    }
}
另一答案

对我来说有用的是,在我的寻呼机适配器的getItem方法中,在列表中保存我自己对我返回的自定义片段的引用。片段寻呼机适配器和片段状态寻呼机适配器似乎遵循的合同意味着getItem(i)返回的最后一个片段将是在onPageSelected(i)方法中刷新的正确片段。

我只使用片段寻呼机适配器和相当少数量的选项卡测试了这种技术。使用状态寻呼机适配器,需要进行一些测试,以查看是否保持对片段的引用会导致内存使用增加。

另一答案

在你的FragmentStatePagerAdapter中使用HashMap来保存创建的Fragments,然后你可以从viewpager容器(活动或片段)访问它们:

public class CustomFragmentPagerAdapter extends FragmentStatePagerAdapter {

    private HashMap<Integer, CustomFragment> fragMap = 
        new HashMap<Integer, CustomFragment>();

    ...

    @Override
    public Fragment getItem(int position) {
        CustomFragment frag = new CustomFragment();
        ...
        fragMap.put(position, frag);
        return frag;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        super.destroyItem(container, position, object);
        fragMap.remove(position);
    }

    public CustomFragment getFragment(int position) {
        return fragMap.get(position);
    }
    ...
}

现在,在viewpager容器(活动或片段)中:

private int lastPage = 0;

...

viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
    @Override
    public void onPageSelected(int position) {

        CustomFragment fragment;
        int currentPage = viewPager.getCurrentItem();

        /* connect the current fragment and disconnect the previous one, in case
           you actually need to disconnect it from the server, 
           otherwise just connect the current fragment.*/
        if(currentPage > lastPage) {
            fragment = yourPagerAdapter.getFragment(currentPage - 1);
            fragment.disconnect();
            fragment = yourPagerAdapter.getFragment(currentPage);
            fragment.connect();
        } else {
            fragment = yourPagerAdapter.getFragment(currentPage + 1);
            fragment.disconnect();
            fragment = yourPagerAdapter.getFragment(currentPage);
            fragment.connect();
        }
        lastPage = currentPage;
    }
});

由于在启动应用程序时未调用onPageChangeListener,因此您需要连接第一个片段。重要的是你将使用getItem()引用yourPagerAdapter.getFragment(currentPage)返回的碎片。

编辑:

我认为这可能是onPageSelected()回调方法的更好逻辑:

viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
        @Override
        public void onPageSelected(int position) {

            CustomFragment fragment;
            int currentPage = viewPager.getCurrentItem();
            Set<Integer> myKeySet = yourPagerAdapter.getKeys();
            for(Integer key : myKeySet) {
                if(key == currentPage) {
                    fragment = yourPagerAdapter.getFragment(key);
                    fragment.connect();
                } else {
                    fragment = yourPagerAdapter.getFragment(key);
                    fragment.disconnect();
                }
            }

        }
    });

但是你需要在qazxsw poi上实现这个方法:

FragmentStatePagerAdapter

并摆脱public Set<Integer> getKeys() { return fragMap.keySet(); } 数据成员。

另一答案

火车晚了。从根本上说,这种方法都不是我最喜欢的。他们很hacky。最好的方法是使用适配器lastPage

setPrimaryItem(ViewGroup container, int position, Object object)onPageSelected里面(最终的int位置)`

代码示例是这样的,

setPrimaryItem' save the current Fragment and use it inside

以上是关于FragmentStatePagerAdapter onPageSelected事件的主要内容,如果未能解决你的问题,请参考以下文章

FragmentStatePagerAdapter 向 TextView 返回错误的位置

如何将 FragmentFactory 与 FragmentStatePagerAdapter 一起使用

getItem 函数在 FragmentStatePagerAdapter 中调用两次?

FragmentPagerAdapter和FragmentStatePagerAdapter区别?

FragmentStatePagerAdapter onPageSelected事件

Android - 使用 FragmentStatePagerAdapter 保存/恢复状态