兩個問題:
1、如果圖片達到500kb每張,你這個划屏會有頓卡;
2、快速滑動有出現0.幾秒的白屏。圖片越大,頓卡越明顯。
回復parcool:500kb的背景算大的了,如果是想做圖片牆,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了。