我理解我可以给setOffscreenPageLimit(int)
的最小数字是1.但我需要一次加载一页因为内存问题。
我是否必须使用旧式tabhost等?或者有没有办法/黑客我可以让我的viewPager一次加载一页?
我的适配器使用ViewHolder patern扩展BaseAdapter。
答案 0 :(得分:26)
我遇到了同样的问题,我找到了解决方案:
<强>步骤:强>
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
做过同样的尝试。如果我找到任何解决方案,我会更新答案。
答案 1 :(得分:16)
据我所知,使用ViewPager 时不可行。至少不是,当你希望你的页面可以刷卡时。 p>
因此解释非常简单: 当您在两个页面之间滑动时,当两个页面都需要可见时会有一个点,因为当其中一个页面不存在时,您无法在两个页面之间滑动。 有关详情,请参阅此问题: ViewPager.setOffscreenPageLimit(0) doesn't work as expected CommonsWare在他answer的评论中提供了很好的解释。
答案 2 :(得分:11)
但我需要一次加载一页因为内存问题。
这假设你得到OutOfMemoryError
s。
我是否必须使用旧式tabhost等?
是,或FragmentTabHost
或操作栏标签。
或者有没有办法/黑客我可以让我的viewPager一次加载一页?
不,原因很简单,ViewPager
一次需要多个页面来进行滑动动画。您可以使用ViewPager
并轻扫来查看此内容。
或者,您可以修复感知到的记忆问题。假设此应用程序与that you reported on earlier today相同,则只使用7MB的堆空间。如果您的剩余堆高度分散,那只会导致OutOfMemoryError
s。有一些内存管理策略(例如inBitmap
BitmapOptions
用于创建来自外部源的位图),有助于解决此类碎片问题。
我的适配器使用ViewHolder patern扩展BaseAdapter。
BaseAdapter
适用于AdapterView
,而不是ViewPager
。
答案 3 :(得分: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);
}
}
`
答案 4 :(得分:1)
覆盖setUserVisibleHint
,并在每个片段中添加如下所示的postDelayed
。
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
if (isVisibleToUser)
Handler().postDelayed({
if (activity != null) {
// Do you stuff here
}
}, 200)
super.setUserVisibleHint(isVisibleToUser)
}
我可以通过这种方式进行管理,并且现在对我来说可以正常工作。
答案 5 :(得分:1)
首先,复制SmartFragmentStatePagerAdapter.java,该文件可在ViewPager中智能缓存已注册的片段。它通过重写InstantiateItem()方法并在内部缓存所有创建的片段来实现。这解决了需要访问ViewPager中的当前项目的常见问题。
现在,我们想在声明适配器时从上面复制的SmartFragmentStatePagerAdapter进行扩展,以便我们可以利用状态分页器的更好的内存管理:
公共抽象类SmartFragmentStatePagerAdapter扩展FragmentStatePagerAdapter { //稀疏数组以跟踪内存中已注册的片段 私有SparseArray registrationFragments = 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);
}
}
//现在从SmartFragmentStatePagerAdapter扩展,以获取更多动态ViewPager项 公共静态类MyPagerAdapter扩展了SmartFragmentStatePagerAdapter { 私有静态整数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;
}
}
答案 6 :(得分:1)
对此我有一个答案。上面提到的setUserVisibleHint()方法已被弃用,您可以使用setMaxLifecycle()方法。要仅加载可见片段,您必须在viewpager适配器中将行为设置为 BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT 。即在构造函数中。为了处理片段,请在片段中使用onResume()方法。
这样,您一次只能在viewpager中加载一个片段。
答案 7 :(得分:0)
您可以使用FragmentStatePagerAdapter。这允许寻呼机保持更少的内存。一旦它们无法访问,它就会从FragmentManager中完全删除Fragment实例。已删除的Fragments的状态存储在FragmentStatePagerAdapter中。返回到现有项目并恢复状态后,将重新创建Fragment实例。
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 :(得分:0)
您实际上不需要自定义ViewPager。
我遇到了同样的问题,我确实这样做了。
setOffscreenPageLimit()
保留为1。onResume
和onPause
生命周期方法。初始化和释放这些生命周期方法中的内存。
答案 9 :(得分:-1)
我知道这是一个老帖子,但我偶然发现了这个问题,如果加载片段,我发现了一个很好的解决方案。简单地说,通过覆盖setUserVisibleHint()来检查用户是否看到了片段。之后加载数据。
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
getData(1, getBaseUrl(), getLink());
}
}