2012-12-31 32 views
16

Tôi đang làm việc trên ứng dụng gamebook hiển thị 12 chế độ xem trong ViewPager. Đây là PagerAdapter tùy chỉnh của tôi:Android setBackgroundNguồn nguyên nhân ngoài bộ nhớ excepiton

private class ImagePagerAdapter extends PagerAdapter { 

    private int[] mImages = new int[] { R.drawable.copertinai, 
      R.drawable.blui, R.drawable.azzurroi, R.drawable.rossoi, 
      R.drawable.gialloi, R.drawable.verdei, R.drawable.rosai, 
      R.drawable.grigioi, R.drawable.neroi, R.drawable.arancionei, 
      R.drawable.marronei, R.drawable.violai, R.drawable.ulm }; 

    @Override 
    public int getCount() { 
     return mImages.length; 
    } 

    @Override 
    public boolean isViewFromObject(View view, Object object) { 
     return view == ((RelativeLayout) object); 
    } 

    @Override 
    public Object instantiateItem(ViewGroup container, int position) { 
     Context context = MainActivity.this; 
     RelativeLayout relLayImageView = new RelativeLayout(context); 
     relLayImageView.setBackgroundResource(mImages[position]); 

     ((ViewPager) container).addView(relLayImageView, new LayoutParams(
       LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); 
     return relLayImageView; 
    } 

    @Override 
    public void destroyItem(ViewGroup container, int position, Object object) { 
     ((ViewPager) container).removeView((RelativeLayout) object); 
     object=null; 
     System.gc(); 
    } 
} 

Trong một số thiết bị nó gây ra một ra khỏi bộ nhớ exceptionr một cách ngẫu nhiên khi dòng mã này được gọi là

relLayImageView.setBackgroundResource(mImages[position]); 

Nhưng trong tất cả các thiết bị tôi nhìn thấy một cái gì đó như thế này trong logcat khi tôi lật các trang:

12-31 00:25:31.655: I/dalvikvm-heap(9767): Grow heap (frag case) to 50.875MB for 10384016-byte allocation 

Ứng dụng này cũng treo trong một số thiết bị cho cùng một vấn đề khi hoạt động khác tôi đặt tài nguyên nền khác nhau vào bố cục chính dựa trên hành động của người dùng. Ở đây mã:

  btn.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View v) { 


       colorButtons.get(indiceColoreAttuale).setBackgroundResource(
           unSelectedColorsRes[indiceColoreAttuale]); 

       switch (index) { 
       case 0: 
        mainLayout.setBackgroundResource(R.drawable.blus); 
        break; 
       case 1: 
        mainLayout 
          .setBackgroundResource(R.drawable.azzurros); 
        break; 
       case 2: 
        mainLayout 
          .setBackgroundResource(R.drawable.rossos); 
        break; 
       case 3: 
        mainLayout 
          .setBackgroundResource(R.drawable.giallos); 
        break; 
       case 4: 
        mainLayout 
          .setBackgroundResource(R.drawable.verdes); 
        break; 
       case 5: 
        mainLayout 
          .setBackgroundResource(R.drawable.rosas); 
        break; 
       case 6:      
        mainLayout 
          .setBackgroundResource(R.drawable.grigios); 
        break; 
       case 7: 
        mainLayout 
          .setBackgroundResource(R.drawable.neros); 
        break; 
       case 8: 
        mainLayout 
          .setBackgroundResource(R.drawable.arancios); 
        break; 
       case 9: 
        mainLayout 
          .setBackgroundResource(R.drawable.marrones); 
        break; 
       case 10: 
        mainLayout 
          .setBackgroundResource(R.drawable.violas); 
        break; 
       } 

       mainLayout.startAnimation(animationShowTextColor); 
       mainLayout.setGravity(Gravity.CENTER_HORIZONTAL); 
       indiceColoreAttuale = index; 
       colorButtons.get(index).setBackgroundResource(
         selectedColorsRes[index]); 

      } 
     }); 

Chạy lại excepiton khi tôi gọi setBackgroundResource() trên mainLayout.

Tôi hy vọng bạn có thể giúp tôi giải quyết vấn đề này, cảm ơn trước!

+0

Có vẻ như bạn đang tải một số hình nền _huge_ và thiết bị không có đủ bộ nhớ cho chúng ... –

+0

Có, nhưng đôi khi xảy ra trên các thiết bị có nhiều bộ nhớ và không xảy ra trong các thiết bị có ít bộ nhớ hơn. tải hình ảnh không thực sự lớn (từ 50 đến 200 kb). – TheModularMind

+0

Chúng không có âm thanh _huge_. Bạn có thể thử 'tái chế các bitmap chính mình trước khi thay đổi tài nguyên nền. Lấy background cũ drawable và sau khi thay đổi nó sẽ thấy nếu nó là một 'BitmapDrawable', nếu nó được gọi là' recycle() 'trên' Bitmap' của nó. –

Trả lời

57

Tôi đã giải quyết! Tất cả các gợi ý của bạn đều tốt nhưng vấn đề thực sự là thư mục "/ drawable"! Tôi đã có tất cả các hình ảnh trong thư mục chung "/ drawable" được hệ thống coi là "/ drawable/mdpi", vì vậy khi tôi đang chạy trong các thiết bị có hdpi trở lên thì hình ảnh được thay đổi kích thước và trở nên quá lớn gây ra lỗi OutOfMemoryException!

Bây giờ tôi đang sử dụng "/ drawable-nodpi" để lưu trữ hình ảnh của mình. Thư mục này hoạt động như "/ drawable" nhưng các hình ảnh không bao giờ được thay đổi kích thước!

+1

Tôi nghĩ bạn có nghĩa là 'drawable-nodpi' –

+0

Cảm ơn, hoạt động như một sự quyến rũ! – ElDoRado1239

+0

Tôi nhận thấy sự sụt giảm đáng kể về mức sử dụng bộ nhớ. Có bất kỳ hạn chế nào đối với giải pháp này không? –

8

Mỗi ứng dụng Android có bộ nhớ giới hạn (heap) có thể được sử dụng bởi máy ảo Dalvik. Nó là 32 MB trên một số thiết bị, nó là 64 MB. Khi bạn thiết lập tài nguyên nền bạn tải tài nguyên đó trên heap. Tài nguyên đó được tải dưới dạng Bitmap - kích thước của nó là chiều rộng * chiều cao * kích thước pixel. Các bitmap thông thường được tải dưới dạng hình ảnh ARGB có 4 byte cho mỗi pixel. Điều đó có nghĩa là tải hình ảnh 1024x768 mất 1024 * 768 * 4 = 3145728 B = 3072 kB = 3 MB trên heap. Khi bạn tải nhiều hình ảnh lớn, nó tiêu thụ tất cả bộ nhớ heap miễn phí và gây ra ngoại lệ bộ nhớ.

Để khắc phục điều này, tốt hơn là tải hình ảnh nhỏ nhất có thể - khi bạn hiển thị hình thu nhỏ của ảnh, đủ để tải nó ở độ phân giải không lớn hơn nhiều so với độ phân giải của phần hiển thị cụ thể. Điều này có nghĩa là khi bạn hiển thị hình ảnh của mình trên màn hình 800x600 thì không đủ để tải hình ảnh 1024x768. Bạn có thể sử dụng BitmapFactory để tải hình ảnh ở độ phân giải nhỏ hơn.

Phương thức sử dụng decodeResource (activity.getResources(), R.drawable.imageId, opts). BitmapFactory.Options opts có tham số inSampleSize, nơi bạn có thể đặt subsampling của hình ảnh. Ngoài ra, tham số inPreferredConfig có thể được sử dụng để đặt RGB_565 thay vì ARGB_8888 trong trường hợp bạn không cần độ trong suốt.

+0

Cảm ơn người đàn ông vì những thông tin này. –

Các vấn đề liên quan