2011-03-21 15 views
7

Rozumiem, że to pytanie jest zadawane kilka razy. Żadne z nich nie jest jasne w sprawie rozwiązania. Pozwól mi wyjaśnić problem.Błąd rozmiaru bitmapy w Androidzie przekracza budżet wm w 2.3.3

  1. Mam aktywność, która ładuje 4 obrazy na raz.
  2. Załaduję obrazy w metodzie onResume().
  3. Aktywność powoduje błąd mapy bitowej podczas ładowania.

Notatki.

  1. Ustawiam obraz przy użyciu wywołania metody setImageResource (R.drawable.xxxx), a nie bezpośrednio bitmapy/rysowania.
  2. Obrazy są skalowane poprawnie.
  3. Aktywność WORKS FINE we wszystkich emulatorach przed 2.3 i jest WORKING FINE w Actual device (Samsung Galaxy 5)
  4. Błąd pojawia się przy pierwszej inicjalizacji i nie jest wywoływane żadne zdarzenie zmiany orientacji.
  5. obrazy mają wymiary 800 x 600 i mają rozmiar 15 kb (każdy).

Powiadom mnie o wszelkich rozwiązaniach. Daj mi też znać, jeśli masz podobne problemy z emulatorem Androida 2.3.3.

[aktualizacja] -snippets

public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
      ... 
    img_topLeft = (ImageView) findViewById(R.id.Img_Alph_Q_TopLeft); 
    img_topRight = (ImageView) findViewById(R.id.Img_Alph_Q_TopRight); 
    img_bottomLeft = (ImageView) findViewById(R.id.Img_Alph_Q_BottomLeft); 
    img_bottomRight = (ImageView) findViewById(R.id.Img_Alph_Q_BottomRight); 
    ... 
    } 
protected void onResume() { 
    super.onResume(); 
      img_topLeft.setImageResource(R.drawable.xxx); 
      img_topRight.setImageResource(R.drawable.xxx); 
      img_bottomLeft.setImageResource(R.drawable.xxx); 
      img_bottomRight.setImageResource(R.drawable.xxx); 
    ... 
    } 

03-21 08:59:17.362: ERROR/dalvikvm-heap(5883): 4320000-byte external allocation too large for this process. 03-21 08:59:17.412: ERROR/GraphicsJNI(5883): VM won't let us allocate 4320000 bytes 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): FATAL EXCEPTION: main 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): java.lang.OutOfMemoryError: bitmap size exceeds VM budget 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.Bitmap.nativeCreate(Native Method) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.Bitmap.createBitmap(Bitmap.java:477) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.Bitmap.createBitmap(Bitmap.java:444) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:349) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:498) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:473) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:336) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.content.res.Resources.loadDrawable(Resources.java:1709) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.content.res.Resources.getDrawable(Resources.java:581) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.widget.ImageView.resolveUri(ImageView.java:501) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.widget.ImageView.setImageResource(ImageView.java:280) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at Quiz.java:124) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): Quiz.onResume(Quiz.java:92) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1150) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.Activity.performResume(Activity.java:3832) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2110) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2135) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1668) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.ActivityThread.access$1500(ActivityThread.java:117) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.os.Handler.dispatchMessage(Handler.java:99) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.os.Looper.loop(Looper.java:123) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.ActivityThread.main(ActivityThread.java:3683) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at java.lang.reflect.Method.invokeNative(Native Method) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at java.lang.reflect.Method.invoke(Method.java:507) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at dalvik.system.NativeStart.main(Native Method)

Dzięki. Zarządzane, aby go rozwiązać. Udostępnianie kodu dla korzyści innych Klasa niestandardowa, która rozwiązała ten problem. w oparciu o link @ Janardhanan.S.

public class BitmapResizer { 

public static Bitmap decodeImage(Resources res, int id ,int requiredSize){ 
    try { 
     BitmapFactory.Options o = new BitmapFactory.Options(); 
     o.inJustDecodeBounds = true; 
     BitmapFactory.decodeResource(res, id, o); 

     //Find the correct scale value. It should be the power of 2. 
     final int REQUIRED_SIZE=requiredSize; 
     int width_tmp=o.outWidth, height_tmp=o.outHeight; 
     int scale=1; 
     while(true){ 
      if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE) 
       break; 
      width_tmp/=2; 
      height_tmp/=2; 
      scale*=2; 
     } 

     //decode with inSampleSize 
     BitmapFactory.Options o2 = new BitmapFactory.Options(); 
     o2.inSampleSize=scale; 
     return BitmapFactory.decodeResource(res, id, o2); 
    } catch (Exception e) { 

    } 
    return null; 
} 

} 

//Class call 
int requiredsize = 100; // Still playing around with this number to find the optimum value 
img_topLeft.setImageBitmap(BitmapResizer.decodeImage(getResources(), 
     AlphResourceSet.R.drawable.xxx, requiredsize)); 
+0

zamieścić swoje onResume kod i może łatwiej będzie Ci pomóc. –

Odpowiedz

3

Bitmapa zużywa dużo miejsca w pamięci. Nie twórz nowej zmiennej bitmapowej dla całego obrazu ładowanego podczas działania, Zamiast tego możesz utworzyć jedną zmienną bitmapy i użyć jej tak często, jak to tylko możliwe.

można użyć tego fragmentu kodu do zmiany rozmiaru bitmapę

http://pastebin.com/D8vbQd2u

+0

Czy muszę sobie z tym poradzić, biorąc pod uwagę, że nie używam zmiennej bitmapowej? Korzystam bezpośrednio z formularza referencyjnego. kod dołączony. – GSree

+0

Nie musisz uwzględniać zmiany rozmiaru dla małych zdjęć, ale 64 KB w jednym działaniu obciąży interfejs użytkownika i pochłonie pamięć. przekonwertuj je na mapę bitową i podaj je w celu wyświetlenia obrazu – Jana

+0

rdhanan.S Co to jest 64kb? Czy istnieje rozmiar obrazu na działanie? Moje obrazy mają rozmiar ~ 15 kb w formacie png. Jedno działanie będzie miało 4 obrazy. Więc ~ 15 x 4 = ~ 60Kb. – GSree

0

Czy możesz opublikować fragment kodu Activity + Stacktrace.

Czy sprawdziłeś już numer Avoiding memory leaks article?

Szczególnie następujące części:

Gdy rozciągliwej jest dołączony do widoku widok jest ustawiony jako zwrotnej rozciągliwych. W powyższym fragmencie kodu oznacza to, że wyciągany jest odnośnik do TextView, który sam ma odniesienie do działania (Kontekst), co z kolei ma odniesienia do niemal wszystkiego (zależnie od kodu).

+0

Sprawdziłem link. Nie jestem pewien, czy mogę zrobić wiele z moim kodem. Zaktualizowano fragment kodu do pytania. Sprawdź proszę i daj mi znać, jeśli będę musiał dokonać pewnych modyfikacji w oparciu o to. – GSree

0

To wydaje się, że obrazy mają bardzo ciężki charakter. Polecam, aby uruchomić AsyncTimer, który faktycznie zwraca instancję bitmapy i w DoBackground() AsyncTask przekazuje identyfikator obrazu i przeskalowuje go do pożądanego rozmiaru, powiedzmy 32 x 32 przy użyciu metody createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) klasy Bitmap.

+0

obrazy mają rozmiar 800 x 600 i mają rozmiar 15 kb (każdy). Czy możesz opublikować krótki opis AsyncTimer? – GSree

Powiązane problemy