首页 > 代码库 > 使用ViewPager时,发生内存溢出OOM问题

使用ViewPager时,发生内存溢出OOM问题

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

       代码如下:

public class GuideActivity extends Activity implements OnPageChangeListener{
	private ViewPager viewPager;
	private GuideAdapter adapter;
	private LinearLayout dotContain;
	private Button btnSure;
	private List<View> mViews=new ArrayList<View>();
	private int[] mResIds=new int[]{
			R.drawable.step01,
			R.drawable.step02,
			R.drawable.step03,
			R.drawable.step04,
			R.drawable.step05,
			R.drawable.step06,
			R.drawable.step07,
			R.drawable.step08,
			R.drawable.step09,
			R.drawable.step10,
			R.drawable.step11
			}; 
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_guide);
		initViews();
		initDatas();
	}
	protected void initViews() {
		viewPager=(ViewPager) findViewById(R.id.vp_guide);
		dotContain=(LinearLayout) findViewById(R.id.layout_dot_contain);
		btnSure=(Button) findViewById(R.id.btn_sure);
		
		adapter=new GuideAdapter(mViews);
	}

	protected void initDatas() {
		
		for (int i = 0; i < mResIds.length; i++) {
			ImageView img=new ImageView(this);
			//延迟设置图片,在PagerAdapter内设置,解决OOM问题
			/*ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(  
	                ViewGroup.LayoutParams.MATCH_PARENT,  
	                ViewGroup.LayoutParams.MATCH_PARENT);
			img.setBackgroundResource(mResIds[i]);
			img.setLayoutParams(params);*/
			mViews.add(img);
		}
		viewPager.setAdapter(adapter);
		viewPager.setOnPageChangeListener(this);
		viewPager.setCurrentItem(0);
		viewPager.setOffscreenPageLimit(1);
		dotContain.getChildAt(0).setSelected(true);
	}
	/**
	 * 
	 * 2014-12-19 上午10:56:19
	 * @param position
	 * @TODO 改变底部图标状态
	 */
	private void chageDotState(final int position){
		int count=dotContain.getChildCount();
		for (int i = 0; i < count; i++) {
			View view=dotContain.getChildAt(i);
			if(position%count==i){
				view.setSelected(true);
			}else{
				view.setSelected(false);
			}
		}
	}
	/**
	 * 
	 * @Create_date 2014-12-19 上午11:09:48
	 * @TODO 适配器
	 */
	class GuideAdapter extends PagerAdapter{
		private List<View> views;
		
		public GuideAdapter(List<View> views) {
			this.views = views;
		}

		@Override
		public int getCount() {
			return views.size();
		}

		@Override
		public boolean isViewFromObject(View arg0, Object arg1) {
			return arg0==arg1;
		}

		@Override
		public void destroyItem(ViewGroup container, int position, Object object) {
			container.removeView(views.get(position));
		}

		@Override
		public int getItemPosition(Object object) {
			return super.getItemPosition(object);
		}
		
		@Override
		public Object instantiateItem(ViewGroup container, int position) {
			//在此设置背景图片,提高加载速度,解决OOM问题
			View view=views.get(position);
			int count=getCount();
			ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(  
	                ViewGroup.LayoutParams.MATCH_PARENT,  
	                ViewGroup.LayoutParams.MATCH_PARENT);
			view.setBackgroundResource(mResIds[position%count]);
			view.setLayoutParams(params);
			container.addView(view,0);
			return views.get(position);
		}
	}

	@Override
	public void onPageScrollStateChanged(int arg0) {
		
	}
	@Override
	public void onPageScrolled(int arg0, float arg1, int arg2) {
		
	}
	@Override
	public void onPageSelected(int arg0) {
		if(arg0<adapter.getCount()-1){
			dotContain.setVisibility(View.VISIBLE);
			btnSure.setVisibility(View.GONE);
			chageDotState(arg0);
		}else{
			dotContain.setVisibility(View.GONE);
			btnSure.setVisibility(View.VISIBLE);
		}
	}
}

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

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

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

使用ViewPager时,发生内存溢出OOM问题