我有一个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()”事件?
提前致谢
答案 0 :(得分:8)
最适合您的解决方案是覆盖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);
}
}
答案 1 :(得分:1)
对我来说有用的是,在我的寻呼机适配器的getItem
方法中,我将自己对我返回的自定义片段的引用保存在列表中。片段寻呼机适配器和片段状态寻呼机适配器似乎遵循的合同意味着getItem(i)
返回的最后一个片段将是在onPageSelected(i)
方法中刷新的正确片段。
我只使用片段寻呼机适配器和相当少数量的标签测试了这种技术。使用状态寻呼机适配器,需要进行一些测试,以查看对片段的引用是否会导致内存使用增加。
答案 2 :(得分:0)
在FragmentStatePagerAdapter
使用HashMap
来保存创建的片段,然后就可以了
稍后从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();
}
}
}
});
但是你需要在FragmentStatePagerAdapter
:
public Set<Integer> getKeys() {
return fragMap.keySet();
}
并删除lastPage
数据成员。
答案 3 :(得分:0)
火车晚了。从根本上说,这种方法都不是我最喜欢的。他们很hacky。最好的方法是使用适配器setPrimaryItem(ViewGroup container, int position, Object object)
on setPrimaryItem' save the current Fragment and use it inside
onPageSelected(final int position)`
代码示例有点像这样,
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
currentFragment = (ProductListFragment) object;
}
// Inside view pager listener use the currently visible fragment
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener()
{
@Override
public void onPageSelected(final int position)
{
currentFragment.onSelected(); // do your thing man
}
});