今天在制作应用某个功能的引导页时,使用了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了。
时间: 2024-10-11 09:36:41