相关文章推荐
高大的大熊猫  ·  zabbix ...·  1 年前    · 
精明的核桃  ·  Oracle 到 Azure SQL ...·  1 年前    · 

如何使我的ViewPager一次只加载一个页面,即setOffscreenPageLimit(0)。

44 人关注

我知道我可以给出的最低数字 setOffscreenPageLimit(int) 是1。但由于内存问题,我需要一次加载一个页面。

我是否必须使用老式的tabhost等?或者有什么方法/黑客可以让我的viewPager一次加载一个页面?

我的适配器扩展了BaseAdapter,并带有ViewHolder属性。

2 个评论
android
android-viewpager
124697
124697
发布于 2013-09-30
9 个回答
Ronak Thakkar
Ronak Thakkar
发布于 2016-11-04
已采纳
0 人赞同

我也有同样的问题,我找到了解决的办法。

Steps:

1) 首先下载 CustomViewPager 。类,从 this link.

2) 如下文所述,使用该类。

在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"/>

现在,一次只加载一个页面。

P.S:根据问题的要求,我已经发布了Viewpager的解决方案。我还没有对TabLayout进行同样的尝试。如果我找到任何解决方案,我将更新答案。

在这个文件中,使用了KeyEventCompat,它可能不被android studio发现,因为KeyEnentCompat类在API级别26.0.0中被废弃了,所以你需要将KeyEventCompat替换为事件,更多细节你可以查看 https://developer.android.com/sdk/support_api_diff/26.0.0-alpha1/changes/android.support.v4.view.KeyEventCompat

RaRa
无法使用TabLayout进行设置,请告知。
@RRR_1173, 使用任何viewpager的一般例子,只需将你的Viewpager替换成CustomViewPager。你可以在这里找到一般的例子。 androidhive.info/2013/10/... 你只需要给CustomClass。
RaRa
tabLayout.setupWithViewPager(customeViewPager); 这里Tablayout不接受自定义类。
无法使用TabLayout进行设置,请告知
谢谢你,伙计。你救了我的命!!。你应该获得奥斯卡奖!我已经挣扎了5天,让它发挥作用!!!
Philipp Jahoda
Philipp Jahoda
发布于 2016-11-04
0 人赞同

据我所知,那是 在使用ViewPager时不可能 .至少,当你想让你的页面可以滑动的时候,是不可以的。

因此,解释是非常简单的。

当你在两个页面之间滑动时,有一个点是两个页面都需要可见,因为 当其中一个不存在时,你不能在两个东西之间刷卡。 在这一点上。

See this question for more: ViewPager.setOffscreenPageLimit(0)不能按预期工作。

CommonsWare 在他的评论中提供了一个很好的解释。 答案 .

John
如果我不想要查看器的刷卡功能怎么办?我正在使用NonSwipeableViewPager,像这样 github.com/nuuneoi/TheCheeseLibrary/blob/master/src/main/java/...
那么就不要使用viewpager ...只需使用一个片段寻呼机或片段状态寻呼机适配器与一个标签布局
CommonsWare
CommonsWare
发布于 2016-11-04
0 人赞同

但由于内存问题,我需要一次加载一个页面。

这假定你得到的是 OutOfMemoryError

我是否要使用旧式的tabhost等?

是的,或 FragmentTabHost ,或行动栏标签。

或者有什么方法/黑客可以让我的viewPager一次加载一个页面?

不是的,原因很简单, ViewPager 需要一次多于一个页面的滑动动画。你可以通过使用 ViewPager 和滑动来看到这一点。

或者,你可以努力解决你认为的记忆问题。假设这个应用程序是同一个 你今天早些时候报道的 ,你只使用了7MB的堆空间。这只会导致 OutOfMemoryError ,如果你的剩余堆是高度碎片化的。有一些内存管理的策略(例如, inBitmap BitmapOptions 上用于从外部来源创建位图),有助于解决这种碎片化问题。

我的适配器扩展了BaseAdapter,并带有ViewHolder属性。

BaseAdapter is for use with AdapterView , not ViewPager .

rVarmag
rVarmag
发布于 2016-11-04
0 人赞同

我对此有一个答案。上述方法setUserVisibleHint()已被废弃,你可以使用setMaxLifecycle()方法。为了只加载可见的片段,你必须将行为设置为 行为_恢复_只恢复当前片段 在viewpager适配器中,即在构造函数中。为了处理片段,在片段中使用onResume()方法。

通过这种方式,你可以在viewpager中一次只加载一个片段。

public static class MyAdapter extends FragmentStatePagerAdapter {
public MyAdapter(FragmentManager fm) {
    super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
@Override
public int getCount() {
    return NUM_ITEMS;
@Override
public Fragment getItem(int position) {
    return ArrayListFragment.newInstance(position);

In Kotlin:

class MyAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm,BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT )

也可与FragmentPagerAdapter(现已弃用)以同样方式使用

你能详细解释一下吗?
你的回答对我很有帮助,请给予更多的解释。
这个答案是唯一有帮助的答案,我们不必覆盖任何已废弃的方法或创建一个自定义视图。
Hardik Hirpara
Hardik Hirpara
发布于 2016-11-04
0 人赞同

通过使用这种方法,你可以在标签布局中用视图分页器每次加载一个页面。 `

  @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);

覆盖setUserVisibleHint并在你的每个片段中添加postDelayed,如下所示。

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

我可以通过这种方式来管理,现在对我来说工作很好。

有什么例子吗?
Naresh Prajapati
Naresh Prajapati
发布于 2016-11-04
0 人赞同

首先,复制SmartFragmentStatePagerAdapter.java,它在我们的ViewPager中提供了注册片段的智能缓存。它通过重写instantiateItem()方法和内部缓存任何创建的片段来实现。这解决了需要访问ViewPager中的当前项目的常见问题。

现在,在声明我们的适配器时,我们要从上面复制的SmartFragmentStatePagerAdapter扩展,这样我们就可以利用状态查询器的更好的内存管理。

public abstract class SmartFragmentStatePagerAdapter extends FragmentStatePagerAdapter {
    // Sparse array to keep track of registered fragments in memory
    private SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
    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;
    
Abarajithan Lv
Abarajithan Lv
发布于 2016-11-04
0 人赞同

你实际上不需要一个自定义的ViewPager。

我有同样的问题,我确实喜欢这个。

  • Keep the setOffscreenPageLimit() as 1.
  • Use fragment's onResume and onPause lifecycle methods.
  • 在这些生命周期方法上初始化和释放内存。

    Ahmed Awad
    Ahmed Awad
    发布于 2016-11-04
    0 人赞同

    我知道这是一个老帖子,但我偶然发现了这个问题,并找到了一个很好的解决方案,如果你的加载片段。简单地说,通过覆盖setUserVisibleHint()来检查用户是否看到这个片段。之后再加载数据。

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