我知道可以给 setOffscreenPageLimit(int)
的最低数字是1。但是由于内存问题,我需要一次只加载一页。
我是否必须使用旧版本的tabhost等?还是有什么方法/技巧可以让我的viewPager一次只加载一页?
我的适配器扩展了具有ViewHolder模式的BaseAdapter。
我知道可以给 setOffscreenPageLimit(int)
的最低数字是1。但是由于内存问题,我需要一次只加载一页。
我是否必须使用旧版本的tabhost等?还是有什么方法/技巧可以让我的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,但是由于 KeyEnentCompat 类在 API 级别 26.0.0 中已被弃用,因此 Android Studio 可能无法找到它,所以您需要将 KeyEventCompat 替换为 event。更多详情请查看 https://developer.android.com/sdk/support_api_diff/26.0.0-alpha1/changes/android.support.v4.view.KeyEventCompat。
由于内存问题,我需要逐个加载页面。
这意味着您正在遭受OutOfMemoryError
错误。
是的,或者使用FragmentTabHost
或选项卡操作栏。
不行,因为简单地说,ViewPager
需要同时加载多个页面以进行滑动动画。您可以通过使用ViewPager
并滑动来查看此情况。
或者,您可以尝试解决感知到的内存问题。假设这个应用程序与您今天早些时候在报告的相同,您只使用了7MB的堆空间。如果剩余的堆高度碎片化,那么这将仅导致OutOfMemoryError
。有一些内存管理策略(例如从外部源创建位图的BitmapOptions
上的inBitmap
),可以帮助解决此类碎片化问题。
我的适配器使用ViewHolder模式扩展了BaseAdapter。
BaseAdapter
用于AdapterView
而非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
一起使用。使用这种方法,您可以在带有视图分页器的选项卡布局中一次加载一个页面。
@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)
}
首先,复制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());
}
}