viewPager--viewpager时,发生内存溢出OOM问题

Posted 左手指月的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了viewPager--viewpager时,发生内存溢出OOM问题相关的知识,希望对你有一定的参考价值。

两个问题:
1、如果图片达到500kb每张,你这个划屏会有顿卡;
2、快速滑动有出现0.几秒的白屏。图片越大,顿卡越明显。

回复parcool:500kb的背景算大的了,如果是想做图片墙,viewpager不适合,可以使用开源的图片墙工具,内存+硬盘缓存

还有哦,你这个图片根本没有手动回收,依然会OOM!

   今天在制作应用某个功能的引导页时,使用了ViewPager进行页面切换,每个页面就放了一个ImageView,使用背景图来进行展示,由于多图(11张)的原因,导致了OOM问题,这里总结一下。

       代码如下:

  1. public class GuideActivity extends Activity implements OnPageChangeListener{  
  2.     private ViewPager viewPager;  
  3.     private GuideAdapter adapter;  
  4.     private LinearLayout dotContain;  
  5.     private Button btnSure;  
  6.     private List<View> mViews=new ArrayList<View>();  
  7.     private int[] mResIds=new int[]{  
  8.             R.drawable.step01,  
  9.             R.drawable.step02,  
  10.             R.drawable.step03,  
  11.             R.drawable.step04,  
  12.             R.drawable.step05,  
  13.             R.drawable.step06,  
  14.             R.drawable.step07,  
  15.             R.drawable.step08,  
  16.             R.drawable.step09,  
  17.             R.drawable.step10,  
  18.             R.drawable.step11  
  19.             };   
  20.     @Override  
  21.     protected void onCreate(Bundle savedInstanceState) {  
  22.         super.onCreate(savedInstanceState);  
  23.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  24.         setContentView(R.layout.activity_guide);  
  25.         initViews();  
  26.         initDatas();  
  27.     }  
  28.     protected void initViews() {  
  29.         viewPager=(ViewPager) findViewById(R.id.vp_guide);  
  30.         dotContain=(LinearLayout) findViewById(R.id.layout_dot_contain);  
  31.         btnSure=(Button) findViewById(R.id.btn_sure);  
  32.           
  33.         adapter=new GuideAdapter(mViews);  
  34.     }  
  35.   
  36.     protected void initDatas() {  
  37.           
  38.         for (int i = 0; i < mResIds.length; i++) {  
  39.             ImageView img=new ImageView(this);  
  40.             //延迟设置图片,在PagerAdapter内设置,解决OOM问题  
  41.             /*ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(   
  42.                     ViewGroup.LayoutParams.MATCH_PARENT,   
  43.                     ViewGroup.LayoutParams.MATCH_PARENT); 
  44.             img.setBackgroundResource(mResIds[i]); 
  45.             img.setLayoutParams(params);*/  
  46.             mViews.add(img);  
  47.         }  
  48.         viewPager.setAdapter(adapter);  
  49.         viewPager.setOnPageChangeListener(this);  
  50.         viewPager.setCurrentItem(0);  
  51.         viewPager.setOffscreenPageLimit(1);  
  52.         dotContain.getChildAt(0).setSelected(true);  
  53.     }  
  54.     /** 
  55.      *  
  56.      * 2014-12-19 上午10:56:19 
  57.      * @param position 
  58.      * @TODO 改变底部图标状态 
  59.      */  
  60.     private void chageDotState(final int position){  
  61.         int count=dotContain.getChildCount();  
  62.         for (int i = 0; i < count; i++) {  
  63.             View view=dotContain.getChildAt(i);  
  64.             if(position%count==i){  
  65.                 view.setSelected(true);  
  66.             }else{  
  67.                 view.setSelected(false);  
  68.             }  
  69.         }  
  70.     }  
  71.     /** 
  72.      *  
  73.      * @Create_date 2014-12-19 上午11:09:48 
  74.      * @TODO 适配器 
  75.      */  
  76.     class GuideAdapter extends PagerAdapter{  
  77.         private List<View> views;  
  78.           
  79.         public GuideAdapter(List<View> views) {  
  80.             this.views = views;  
  81.         }  
  82.   
  83.         @Override  
  84.         public int getCount() {  
  85.             return views.size();  
  86.         }  
  87.   
  88.         @Override  
  89.         public boolean isViewFromObject(View arg0, Object arg1) {  
  90.             return arg0==arg1;  
  91.         }  
  92.   
  93.         @Override  
  94.         public void destroyItem(ViewGroup container, int position, Object object) {  
  95.             container.removeView(views.get(position));  
  96.         }  
  97.   
  98.         @Override  
  99.         public int getItemPosition(Object object) {  
  100.             return super.getItemPosition(object);  
  101.         }  
  102.           
  103.         @Override  
  104.         public Object instantiateItem(ViewGroup container, int position) {  
  105.             //在此设置背景图片,提高加载速度,解决OOM问题  
  106.             View view=views.get(position);  
  107.             int count=getCount();  
  108.             ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(    
  109.                     ViewGroup.LayoutParams.MATCH_PARENT,    
  110.                     ViewGroup.LayoutParams.MATCH_PARENT);  
  111.             view.setBackgroundResource(mResIds[position%count]);  
  112.             view.setLayoutParams(params);  
  113.             container.addView(view,0);  
  114.             return views.get(position);  
  115.         }  
  116.     }  
  117.   
  118.     @Override  
  119.     public void onPageScrollStateChanged(int arg0) {  
  120.           
  121.     }  
  122.     @Override  
  123.     public void onPageScrolled(int arg0, float arg1, int arg2) {  
  124.           
  125.     }  
  126.     @Override  
  127.     public void onPageSelected(int arg0) {  
  128.         if(arg0<adapter.getCount()-1){  
  129.             dotContain.setVisibility(View.VISIBLE);  
  130.             btnSure.setVisibility(View.GONE);  
  131.             chageDotState(arg0);  
  132.         }else{  
  133.             dotContain.setVisibility(View.GONE);  
  134.             btnSure.setVisibility(View.VISIBLE);  
  135.         }  
  136.     }  
  137. }  

代码中已经进行了说明。一开始,使用了一个for循环,将所有的ImageView设置了背景并添加到List<View>中,这样导致,一点进这个界面时,有点卡顿,并且有时还会出现OOM问题。

 

        解决办法就是:在for循环内只将ImageView对象添加到List<View>中,并不对其设置背景资源,将该步骤延迟到PagerAdapter$instantiateItem()中再进行设置。

        说明:页面过多会报OOM的原因是,当ImageView在调用setBackgroundResource时,底层会调用BitmapFactory.decodeResource进行解码,而这个过程是耗时的,也很容易就OOM了,因此在for循环内进行多图设置的话就导致卡顿甚至OOM了。

 

以上是关于viewPager--viewpager时,发生内存溢出OOM问题的主要内容,如果未能解决你的问题,请参考以下文章

ViewPager 系列之 打造一个通用的 ViewPager

ViewPager 系列之 打造一个通用的 ViewPager

无法使用数据绑定绑定 viewpager2 数据

带有 SlidingTabLayout 的 ViewPager 中的 Listview - 高度问题

ViewPager1嵌入ViewPager2,两者重叠,怎么禁止ViewPager1的滑动功能?

使用 viewpager 实现滑动抽屉,滑动抽屉位于 viewpager 上