FragmentStatePagerAdapter处理getItem()位置

3
我尝试过这种方法,但错误的列表被绑定到recyclerview上了。我也尝试了SparseArray,但它也不管用。当我启动MainActivity时,getItem()方法会被调用两次。我应该如何处理返回的位置呢? 我尝试了返回viewpager的currentItem,但它也不起作用。 MainActivity
public class PagerAdapter extends FragmentStatePagerAdapter {
    int mNumOfTabs;


    public PagerAdapter(android.support.v4.app.FragmentManager fragmentManager, int tabCount) 
    {
        super(fragmentManager);
        this.mNumOfTabs = tabCount;    
    } 

    @Override
    public Fragment getItem(int position) {

        return Categories_Fragment.newInstance(position);

    }

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

}

Categories_Fragment

public class Categories_Fragment extends Fragment 
{
private RecyclerView lvMessages; 
private int fromPage;


public static Categories_Fragment newInstance(int num) {
    Categories_Fragment f = new Categories_Fragment();

    // Supply num input as an argument.
    Bundle args = new Bundle();
    args.putInt("from", num);
    f.setArguments(args);

    return f; 
}


@Override
public void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    fromPage = getArguments().getInt("from"); 


}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {      
    // TODO Auto-generated method stub  
    View rootView = inflater.inflate(R.layout.categories_filter, container, false); 
    lvMessages    = (RecyclerView)rootView.findViewById(R.id.lv_categories_filter);

    LinearLayoutManager x =  new LinearLayoutManager(getActivity()); 
    x.setOrientation(LinearLayoutManager.VERTICAL); 

    lvMessages.setLayoutManager(x);   


    return rootView; 
}


@Override
public void onActivityCreated(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onActivityCreated(savedInstanceState);

    // bind different data to the RecyclerView based on fromPage value. 

    }

}

尝试将您的Fragment设置为静态:public static class Categories_Fragment extends Fragment - Alexander Tumanin
请发布引用PagerAdapter的代码。我认为主要问题是“getItem()被调用两次...” - The Original Android
这对你应该有效。实现一个接口,只有在片段可见时才会被调用。https://dev59.com/42Eh5IYBdhLWcg3w32xG#24386516 - shreyas
4个回答

2
这可能是重点所在...
@Override
public void setUserVisibleHint(boolean isVisible) {
    super.setUserVisibleHint(isVisible);
    if (isVisible) {
        // bind to stuff using value of fromPage from here
    }
}

public void setUserVisibleHint (boolean isVisibleToUser): 设置一个提示给系统,告诉它这个片段的UI是否当前对用户可见。这个提示默认为true,并且在片段实例状态保存和恢复时是持久的。

如果我正确理解您的问题,可能的问题是pager传递了它的“最后已知”位置,这并不一定是当前显示在设备屏幕上的片段的位置。

更新:这里有一个完整的示例,使用ViewPager处理相同的片段但传递不同的数据:

public class ViewPagerAdapter extends FragmentStatePagerAdapter {

    private JSONArray itemsArray;
    private int fragmentId;

    public ViewPagerAdapter(JSONArray itemsArray, int fragmentId, FragmentManager manager) {
        super(manager);
        this.itemsArray = itemsArray;
        this.fragmentId = fragmentId;
    }

    @Override
    public Fragment getItem(int position) {
        JSONObject itemObject = new Listing(itemsArray, position).getObject();
        Bundle bundle = new Bundle();
        bundle.putString("item_object", itemObject.toString());
        bundle.putInt("item_position", position);
        bundle.putInt("total_items", getCount());
        bundle.putInt("fragment_Id", fragmentId);
        Fragment fragment = new ListingFragment();
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public int getCount() {
        return itemsArray.length();
    }

}

以下是 Listings 碎片(不包括无关紧要的部分):

这里是 Listings 碎片(减去了不重要的部分):

public class ListingFragment extends Fragment {

    private Listing listing;

    private String itemObject;
    private int itemPosition;
    private int totalItems;
    private int fragmentId;

    public ListingFragment() { }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle bundle = getArguments();
        itemObject = bundle.getString("item_object");
        itemPosition = bundle.getInt("item_position");
        totalItems = bundle.getInt("total_items");
        fragmentId = bundle.getInt("fragment_Id");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
        View view = ...
        // nothing special to see here, just the usual stuff
        return view;
    }

    @Override
    public void setUserVisibleHint(boolean isVisible) {
        super.setUserVisibleHint(isVisible);
        if (isVisible) {
            // send fragmentID to wherever you want to use it
            // such as your recyclerview/adapter from here
         }
     }

}

我希望这个例子能为您提供一些启示,我知道它对我来说总是绝不会失效。


我认为如果我有不同类型的片段,这将起作用。但是我正在使用一个带有传递参数的单个片段。 - Anirudh
它应该适用于单个片段。我曾经遇到过一个获取新闻标题的应用程序完全相同的问题:每个片段都是相同的,包含一个recyclerview,但显示的标题因我在setUserVisibleHint()中传递的类别ID而异。如果我从getItem()中传递ID,则片段将加载来自下一个类别(或上一个类别,具体取决于我向哪个方向滑动),因为它保存的ID是最后一个缓存在分页器中的ID,而不是当前可见片段的ID。 - mjp66
Neil Agarwal 在下面的回答中解释了多个 getItem() 调用,因为分页器正在获取当前可见的碎片以及其后面的碎片。 - mjp66
你能否更新一下你的回答并贴上一小段代码呢? - Anirudh
当然,稍等一下... ;) - mjp66
显示剩余2条评论

0

使用 FragmentStatePagerAdapterHashMap<Integer,Demo_Fragment>

 public class ViewPagerAdapter extends FragmentStatePagerAdapter {
        List<String> mList;

        public ViewPagerAdapter(FragmentManager fm, List<String> list) {
            super(fm);
            mList = list;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            String  title = mList.get(position);
            return title;
        }

        public int getCount() {
            return mList.size();
        }

        public Fragment getItem(int position) {
            Demo_Fragment fragment = new Demo_Fragment();
            Bundle bundle = new Bundle();
            bundle.putString("text",mList.get(position));
            fragment.setArguments(bundle);
            fragment.setTags(position);
            mPageReferenceMap.put(position, fragment);

            return fragment;
        }

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

        public int getItemPosition(Object item) {
            Demo_Fragment fragment = (Demo_Fragment) item;
            int position = fragment.getTags();
            if (position >= 0) {
                return position;
            } else {
                return POSITION_NONE;
            }
        }
    }

获取 Fragment

public Demo_Fragment getFragment(int key) {
        return mPageReferenceMap.get(key);
    }

addOnPageChangeListener ViewPager 中获取当前片段

mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageSelected(int position) {
                final Demo_Fragment demo_Fragment = getFragment(mViewPager.getCurrentItem());
                final String str = mArrString.get(mViewPager.getCurrentItem());
                demo_Fragment.updateView(str);
                showDialog();
                mRunnable = new Runnable() {
                    @Override
                    public void run() {
                        randomGenerator = new Random();
                        randomInt = randomGenerator.nextInt(10000);
                        demo_Fragment.updateView(str +"\n" +randomInt+"-Updated Value");
                        hideDialog();
                    }
                };
                mHandler.postDelayed(mRunnable, 2000);


            }

            @Override
            public void onPageScrollStateChanged(int state) {
            }
        });

工作示例 - 点击这里


0

你创建了一个名为PagerAdapter的类,这是一个Android抽象类,这很可疑。请将其重命名为唯一的名称,例如MyPagerAdapter。


@Anirudh,它是否仍在调用getItem()两次?还是根本没有调用? - The Original Android

0
getItem() 被调用两次的原因是由于在 ViewPager 中分配给 offScreenPageLimit 的默认值。
您可以使用 ViewPager 类的 setOffscreenPageLimit(int limit) 方法将 offScreenPageLimit 设置为 1 或 0,这将解决调用 getItem() 两次的问题。
因此,如果 getItem() 只被调用一次,则您将在片段中获得正确的位置值,并且您的问题将得到解决。
请查看链接以获取方法定义和描述。

http://developer.android.com/reference/android/support/v4/view/ViewPager.html#setOffscreenPageLimit(int)


在发布问题之前就尝试过了,但对我无效。 - Anirudh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接