40

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

我将不得不使用旧式tabhost等吗?或者有没有办法/hack我可以让我的viewPager一次加载一个页面?

我的适配器使用 ViewHolder 模式扩展了 BaseAdapter。

4

9 回答 9

42

我遇到了同样的问题,我找到了解决方案:

脚步:

1)首先从这个链接下载CustomViewPager课程。

2)使用该类,如下所述:

在 Java 中:

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

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

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

PS:根据问题的要求,我已经发布了解决方案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

于 2017-06-07T06:24:43.420 回答
18

据我所知,使用 ViewPager 时这是不可能的。至少不是,当您希望您的页面可滑动时。

因此,解释非常简单:

当您在两个页面之间滑动时,当两个页面都需要可见时,会有一个点,因为当其中一个甚至不存在时,您无法在两个事物之间滑动

有关更多信息,请参阅此问题:ViewPager.setOffscreenPageLimit(0) 无法按预期工作

CommonsWare在他的回答的评论中提供了很好的解释。

于 2013-09-30T14:40:03.370 回答
12

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

那假设您正在获得OutOfMemoryErrors。

我将不得不使用旧式tabhost等吗?

是,或FragmentTabHost,或操作栏选项卡。

或者有没有办法/hack我可以让我的viewPager一次加载一个页面?

不,原因很简单,ViewPager滑动动画一次需要多个页面。您可以通过使用 aViewPager和滑动来查看这一点。

或者,您可以努力解决您感知到的记忆问题。假设这个应用程序与您今天早些时候报告的相同,您只使用了 7MB 的堆空间。OutOfMemoryError如果您的剩余堆高度碎片化,那只会导致s 。有一些内存管理策略(例如,inBitmapBitmapOptions外部源创建位图)有助于解决这种碎片问题。

我的适配器使用 ViewHolder 模式扩展了 BaseAdapter。

BaseAdapter与 一起使用AdapterView,而不是ViewPager

于 2013-09-30T14:39:47.030 回答
3

通过使用此方法,您可以使用视图分页器在选项卡布局中一次加载一页

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

        }
    }

`

于 2018-10-31T06:36:02.660 回答
3

我对此有一个答案。上述方法 setUserVisibleHint() 已弃用,您可以使用 setMaxLifecycle() 方法。要仅加载可见片段,您必须在 viewpager 适配器中将行为设置为BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT 。IE; 在构造函数中。为了处理片段,请在片段中使用 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);
}

}

在科特林:

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

也以同样的方式使用 with FragmentPagerAdapter(现已弃用)

于 2020-03-24T13:51:10.897 回答
2

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

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

我可以通过这种方式进行管理,并且现在对我来说工作正常。

于 2018-10-20T07:47:02.600 回答
1

首先,复制 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;
        }

    }
于 2019-09-03T06:55:41.133 回答
0

您实际上不需要自定义 ViewPager。

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

  • 保持setOffscreenPageLimit()为 1。
  • 使用片段onResumeonPause生命周期方法。

初始化和释放这些生命周期方法的内存。

于 2020-09-23T10:26:55.477 回答
-2

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

    @Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        getData(1, getBaseUrl(), getLink());
    }
}
于 2016-11-03T19:24:56.843 回答