问题
I tried this, but wrong lists get binded to the recyclerview. I tried SparseArray as well, even that doesn't work. getItem() gets called twice when i start Mainactivity. How do I handle the position returned? I tried returning viewpager currentItem, even that doesn't work.
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.
}
}
回答1:
Here's what may be the kicker...
@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): Set a hint to the system about whether this fragment's UI is currently visible to the user. This hint defaults to true and is persistent across fragment instance state save and restore.
What might be the problem (if I'm understanding your question correctly) is the pager is passing along its "last known" position, which doesn't necessarily mean is the position of the fragment that is currently being displayed on the device screen.
UPDATE: here's a complete example with a ViewPager handling the same fragment but with different data passed to it:
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();
}
}
Here's the Listings fragment (minus unimportant bits):
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
}
}
}
I hope the example sheds some light, I know it works for me without fail.
回答2:
It is suspicious that you created a class called PagerAdapter, which is an Android abstract class. Rename it to a unique name like MyPagerAdapter.
回答3:
The reason why the getItem() is called twice is because of the default value assigned to offScreenPageLimit in ViewPager.
you can set the offScreenPageLimit to 1 or 0 using setOffscreenPageLimit (int limit) method of ViewPager class, and this will solve your problem of calling getItem() twice.
Hence, if getItem() is called once, then you will get the correct position value in the fragment and your problem wil lbe resolved.
checkout the link for method definition and description
http://developer.android.com/reference/android/support/v4/view/ViewPager.html#setOffscreenPageLimit(int)
回答4:
Using FragmentStatePagerAdapter
,HashMap<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;
}
}
}
For get Fragment
public Demo_Fragment getFragment(int key) {
return mPageReferenceMap.get(key);
}
For get current Fragment in 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) {
}
});
Working example - Click Here
来源:https://stackoverflow.com/questions/33706456/fragmentstatepageradapter-handling-getitem-position