How can make my ViewPager load only one page at a time ie setOffscreenPageLimit(0);

人走茶凉 提交于 2019-12-17 02:49:07

问题


I understand the lowest number I can give setOffscreenPageLimit(int) is 1. but I need to load one page at a time because memory problems.

Am i going to have to use the old style tabhost etc? or is there a way/hack I can make my viewPager load one page at a time?

My Adapter extends BaseAdapter with the ViewHolder patern.


回答1:


I was having the same problem and I found the solution for it:

Steps:

1) First Download the CustomViewPager Class from this link.

2) Use that class as mentioned below:

In Java:

CustomViewPager mViewPager;
mViewPager = (CustomViewPager) findViewById(R.id.swipePager);
mViewPager.setOffscreenPageLimit(0);

In XML:

<com.yourpackagename.CustomViewPager 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/swipePager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

Now only one page will be loaded at once.

P.S: As per the question's requirement, I have posted the solution for Viewpager. I haven't tried the same with TabLayout yet. If I will find any solution for that I will update the answer.




回答2:


As far as I know, that is not possible when using the ViewPager. At least not, when you want your pages to be swipe-able.

The explaination therefore is very simple:

When you swipe between two pages, there is a Point when both pages need to be visible, since you cannot swipe between two things when one of those does not even exist at that point.

See this question for more: ViewPager.setOffscreenPageLimit(0) doesn't work as expected

CommonsWare provided a good explaination in the comments of his answer.




回答3:


but I need to load one page at a time because memory problems.

That presumes that you are getting OutOfMemoryErrors.

Am i going to have to use the old style tabhost etc?

Yes, or FragmentTabHost, or action bar tabs.

or is there a way/hack I can make my viewPager load one page at a time?

No, for the simple reason that ViewPager needs more than one page at a time for the sliding animation. You can see this by using a ViewPager and swiping.

Or, you can work on fixing your perceived memory problems. Assuming this app is the same one that you reported on earlier today, you are only using 7MB of heap space. That will only result in OutOfMemoryErrors if your remaining heap is highly fragmented. There are strategies for memory management (e.g., inBitmap on BitmapOptions for creating bitmaps from external sources) that help address such fragmentation concerns.

My Adapter extends BaseAdapter with the ViewHolder patern.

BaseAdapter is for use with AdapterView, not ViewPager.




回答4:


By using this method you can load one page at time in tab layout with view pager`

  @Override
    public void onResume() {
        super.onResume();
        if (getUserVisibleHint() && !isVisible) {
            Log.e("~~onResume: ", "::onLatestResume");
           //your code
        }
        isVisible = true;
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);

        if (isVisibleToUser && isVisible) {
            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                   //your code
                }
            }, 500);

        }
    }

`




回答5:


Override the setUserVisibleHint and add postDelayed like below in your every fragments.

override fun setUserVisibleHint(isVisibleToUser: Boolean) {
    if (isVisibleToUser)
        Handler().postDelayed({
            if (activity != null) {
                // Do you stuff here 
            }
        }, 200)
    super.setUserVisibleHint(isVisibleToUser)
}

I can manage by this way and its working fine now for me.




回答6:


First, copy in the SmartFragmentStatePagerAdapter.java which provides the intelligent caching of registered fragments within our ViewPager. It does so by overriding the instantiateItem() method and caching any created fragments internally. This solves the common problem of needing to access the current item within the ViewPager.

Now, we want to extend from SmartFragmentStatePagerAdapter copied above when declaring our adapter so we can take advantage of the better memory management of the state pager:

public abstract class SmartFragmentStatePagerAdapter extends FragmentStatePagerAdapter { // Sparse array to keep track of registered fragments in memory private SparseArray registeredFragments = new SparseArray();

public SmartFragmentStatePagerAdapter(FragmentManager fragmentManager) {
    super(fragmentManager);
}

// Register the fragment when the item is instantiated
@Override
public Object instantiateItem(ViewGroup container, int position) {
    Fragment fragment = (Fragment) super.instantiateItem(container, position);
    registeredFragments.put(position, fragment);
    return fragment;
}

// Unregister when the item is inactive
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    registeredFragments.remove(position);
    super.destroyItem(container, position, object);
}

// Returns the fragment for the position (if instantiated)
public Fragment getRegisteredFragment(int position) {
    return registeredFragments.get(position);
}

}

// Extend from SmartFragmentStatePagerAdapter now instead for more dynamic ViewPager items public static class MyPagerAdapter extends SmartFragmentStatePagerAdapter { private static int NUM_ITEMS = 3;

    public MyPagerAdapter(FragmentManager fragmentManager) {
        super(fragmentManager);
    }

    // Returns total number of pages
    @Override
    public int getCount() {
        return NUM_ITEMS;
    }

    // Returns the fragment to display for that page
    @Override
    public Fragment getItem(int position) {
        switch (position) {
        case 0: // Fragment # 0 - This will show FirstFragment
            return FirstFragment.newInstance(0, "Page # 1");
        case 1: // Fragment # 0 - This will show FirstFragment different title
            return FirstFragment.newInstance(1, "Page # 2");
        case 2: // Fragment # 1 - This will show SecondFragment
            return SecondFragment.newInstance(2, "Page # 3");
        default:
            return null;
        }
    }

    // Returns the page title for the top indicator
    @Override
    public CharSequence getPageTitle(int position) {
        return "Page " + position;
    }

}



回答7:


You can use FragmentStatePagerAdapter. This allows the pager to hold on to much less memory. It completely removes Fragment instances from the FragmentManager once they are out of reach. The state of the removed Fragments is stored inside the FragmentStatePagerAdapter. The Fragment instance is recreated once you return back to an existing item and the state is restored.

public static class MyAdapter extends FragmentStatePagerAdapter {
    public MyAdapter(FragmentManager fm) {
        super(fm);
    }

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

    @Override
    public Fragment getItem(int position) {
        return ArrayListFragment.newInstance(position);
    }
}



回答8:


I know this is an old post, but I stumbled upon this issue and found a good fix if your loading fragments. Simply, check if the user is seeing the fragment or not by overriding the setUserVisibleHint(). After that load the data.

    @Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        getData(1, getBaseUrl(), getLink());
    }
}


来源:https://stackoverflow.com/questions/19096868/how-can-make-my-viewpager-load-only-one-page-at-a-time-ie-setoffscreenpagelimit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!