【发布时间】:2013-10-06 11:20:35
【问题描述】:
我知道我可以给setOffscreenPageLimit(int) 的最小数字是 1。但由于内存问题,我需要一次加载一页。
我将不得不使用旧样式的 tabhost 等吗?或者有没有办法/hack我可以让我的viewPager一次加载一个页面?
我的适配器使用 ViewHolder 模式扩展 BaseAdapter。
【问题讨论】:
-
检查这个answer。它解决了我的问题。
我知道我可以给setOffscreenPageLimit(int) 的最小数字是 1。但由于内存问题,我需要一次加载一页。
我将不得不使用旧样式的 tabhost 等吗?或者有没有办法/hack我可以让我的viewPager一次加载一个页面?
我的适配器使用 ViewHolder 模式扩展 BaseAdapter。
【问题讨论】:
我遇到了同样的问题,我找到了解决方案:
步骤:
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
【讨论】:
据我所知,在使用 ViewPager 时是不可能的。至少不是,当您希望您的页面可滑动时。
因此解释很简单:
当您在两个页面之间滑动时,当两个页面都需要可见时,会有一个点,因为 当其中一个甚至不存在时,您无法在两个事物之间滑动。 p>
请参阅此问题了解更多信息:ViewPager.setOffscreenPageLimit(0) doesn't work as expected
CommonsWare 在他的answer 的cmets 中提供了很好的解释。
【讨论】:
但由于内存问题,我需要一次加载一页。
假设您收到的是OutOfMemoryErrors。
我将不得不使用旧样式的 tabhost 等吗?
是,或FragmentTabHost,或操作栏标签。
或者有没有办法/破解我可以让我的 viewPager 一次加载一个页面?
不,原因很简单,ViewPager 一次需要多个页面来播放滑动动画。您可以使用ViewPager 并滑动查看。
或者,您可以努力解决您感知到的记忆问题。假设这个应用程序是同一个that you reported on earlier today,你只使用了 7MB 的堆空间。如果您的剩余堆高度碎片化,那只会导致OutOfMemoryErrors。有一些内存管理策略(例如,BitmapOptions 上的inBitmap 用于从外部源创建位图)有助于解决此类碎片问题。
我的适配器使用 ViewHolder 模式扩展 BaseAdapter。
BaseAdapter 用于AdapterView,而不是ViewPager。
【讨论】:
通过使用此方法,您可以使用视图分页器在选项卡布局中一次加载一个页面`
@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() 已弃用,您可以使用 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(现已弃用)一起使用
【讨论】:
覆盖setUserVisibleHint 并在每个片段中添加postDelayed,如下所示。
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
if (isVisibleToUser)
Handler().postDelayed({
if (activity != null) {
// Do you stuff here
}
}, 200)
super.setUserVisibleHint(isVisibleToUser)
}
我可以通过这种方式进行管理,并且现在对我来说工作正常。
【讨论】:
首先,复制 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;
}
}
【讨论】:
您实际上不需要自定义 ViewPager。
我有同样的问题,我确实喜欢这个。
setOffscreenPageLimit() 为1。onResume 和onPause 生命周期方法。初始化并释放这些生命周期方法的内存。
【讨论】:
我知道这是一篇旧帖子,但我偶然发现了这个问题,并在加载片段时找到了一个很好的解决方案。简单地说,通过覆盖 setUserVisibleHint() 来检查用户是否看到了片段。之后加载数据。
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
getData(1, getBaseUrl(), getLink());
}
}
【讨论】: