【问题标题】:How can make my ViewPager load only one page at a time ie setOffscreenPageLimit(0);如何让我的 ViewPager 一次只加载一个页面,即 setOffscreenPageLimit(0);
【发布时间】:2013-10-06 11:20:35
【问题描述】:

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

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

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

【问题讨论】:

标签: android android-viewpager


【解决方案1】:

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

步骤:

1)首先从this链接下载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"/>

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

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

【讨论】:

  • 无法使用 TabLayout 进行设置,请告知
  • @RRR_1173,对 viewpager 使用任何通用示例,只需将 Viewpager 替换为 CustomViewPager。您可以在此处找到一般示例:androidhive.info/2013/10/… 您只需要提供 CustomClass。
  • tabLayout.setupWithViewPager(customeViewPager);这里 Tablayout 不接受自定义类。
  • 无法使用 TabLayout 进行设置,请告知
  • 谢谢伙计。你救了我的命!!!你值得奥斯卡奖!!我一直在努力让它工作 5 天!!!
【解决方案2】:

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

因此解释很简单:

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

请参阅此问题了解更多信息:ViewPager.setOffscreenPageLimit(0) doesn't work as expected

CommonsWare 在他的answer 的cmets 中提供了很好的解释。

【讨论】:

【解决方案3】:

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

假设您收到的是OutOfMemoryErrors。

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

是,或FragmentTabHost,或操作栏标签。

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

不,原因很简单,ViewPager 一次需要多个页面来播放滑动动画。您可以使用ViewPager 并滑动查看。

或者,您可以努力解决您感知到的记忆问题。假设这个应用程序是同一个that you reported on earlier today,你只使用了 7MB 的堆空间。如果您的剩余堆高度碎片化,那只会导致OutOfMemoryErrors。有一些内存管理策略(例如,BitmapOptions 上的inBitmap 用于从外部源创建位图)有助于解决此类碎片问题。

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

BaseAdapter 用于AdapterView,而不是ViewPager

【讨论】:

    【解决方案4】:

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

      @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】:

      我对此有一个答案。上述方法 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);
      }
      

      }

      在 Kotlin 中:

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

      也以同样的方式与FragmentPagerAdapter(现已弃用)一起使用

      【讨论】:

      • 能详细解释一下吗?
      • 你的回答对我有帮助,请多解释
      • 这个答案是唯一有用的答案,我们不必重写任何已弃用的方法或创建自定义视图。
      【解决方案6】:

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

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

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

      【讨论】:

      • 请问有什么例子吗?
      【解决方案7】:

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

      【讨论】:

        【解决方案8】:

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

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

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

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

        【讨论】:

          【解决方案9】:

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

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

          【讨论】:

          • 片段可见但尚未初始化,此解决方案会导致问题。
          • 您始终可以添加一个布尔检查并从 oncreate 方法重新调用它。我已经使用这个解决方案一个多月了,应用运行良好。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-10-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多