今天在制作应用某个功能的引导页时,使用了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了。