2013-03-15 2 views
1

나는 150KB 이하의 서로 다른 크기의 이미지를 적어도 28 개 이상로드하는 간단한 정적 이미지 갤러리를 사용하고 있습니다.간단한 정적 갤러리의 경우 메모리 부족 예외가 발생했습니다.

그리고 난 여기에 두 가지 문제주의 :이 활동이 세 가지에 갈 때

1) 느린 스크롤 2) 메모리 예외의 아웃 - 번.

어떤 사람이 나를 안내하고 문제를 해결하는 방법은 무엇입니까?

어떤 도움

로그인 고양이를 감상 할 수있다 :

03-15 15:32:55.899: E/AndroidRuntime(14662): java.lang.OutOfMemoryError: bitmap size exceeds VM budget 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:563) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:439) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.content.res.Resources.loadDrawable(Resources.java:1709) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.content.res.Resources.getDrawable(Resources.java:581) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.ImageView.resolveUri(ImageView.java:501) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.ImageView.setImageResource(ImageView.java:280) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at com.tackfu.Art$ImageAdapter.getView(Art.java:84) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.AbsListView.obtainView(AbsListView.java:1515) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.GridView.makeAndAddView(GridView.java:1269) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.GridView.makeRow(GridView.java:315) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.GridView.fillDown(GridView.java:268) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.GridView.fillGap(GridView.java:235) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.AbsListView.trackMotionScroll(AbsListView.java:4063) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.AbsListView.onTouchEvent(AbsListView.java:2471) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.view.View.dispatchTouchEvent(View.java:3885) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:903) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1750) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1135) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.app.Activity.dispatchTouchEvent(Activity.java:2096) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1734) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2216) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.view.ViewRoot.handleMessage(ViewRoot.java:1887) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.os.Handler.dispatchMessage(Handler.java:99) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.os.Looper.loop(Looper.java:130) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.app.ActivityThread.main(ActivityThread.java:3687) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at java.lang.reflect.Method.invokeNative(Native Method) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at java.lang.reflect.Method.invoke(Method.java:507) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625) 
03-15 15:32:55.899: E/AndroidRuntime(14662): at dalvik.system.NativeStart.main(Native Method) 

활동 코드 : 150킬로바이트 크기

@Override 
     public void onCreate(Bundle savedInstanceState) { 

super.onCreate(savedInstanceState); 
      setContentView(R.layout.art); 

GridView gridview = (GridView) findViewById(R.id.gridv 
gridview.setAdapter(new ImageAdapter(this)); 

} 

public class ImageAdapter extends BaseAdapter { 
      private Context mContext; 

      public ImageAdapter(Context c) { 
       mContext = c; 
      } 

      public int getCount() { 
       return mThumbIds.length; 
      } 

      public Object getItem(int position) { 
       return null; 
      } 

      public long getItemId(int position) { 
       return 0; 
      } 

      // create a new ImageView for each item referenced by the Adapter 
      public View getView(int position, View convertView, ViewGroup parent) { 
       ImageView imageView; 
       if (convertView == null) { // if it's not recycled, initialize some attributes 
        imageView = new ImageView(mContext); 
        imageView.setLayoutParams(new GridView.LayoutParams(85, 85)); 
        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); 
        imageView.setPadding(8, 8, 8, 8); 
       } else { 
        imageView = (ImageView) convertView; 
       } 

       imageView.setImageResource(mThumbIds[position]); 
       return imageView; 
      } 

      // references to our images 
      private Integer[] mThumbIds = { 
        R.drawable.i1, R.drawable.i2, 
        R.drawable.i3, R.drawable.i4, 
        R.drawable.i5, R.drawable.i6, 
        R.drawable.i7, R.drawable.i8, 
        R.drawable.i9, R.drawable.i10, 
        R.drawable.i11, R.drawable.i12, 
        R.drawable.i13,R.drawable.i14, 
        R.drawable.i15,R.drawable.i16, 
        R.drawable.i17,R.drawable.i18, 
        R.drawable.i19,R.drawable.i20, 
        R.drawable.i21, R.drawable.i22, 
        R.drawable.i23, R.drawable.i24, 
        R.drawable.i26, R.drawable.i28, 
        R.drawable.i29, R.drawable.i30 
      }; 
     } 
+0

이 게시물을 읽었습니까? 메모리를 부족하게 만들었습니다. 활동을 시작하면이 게시물을 읽습니까? http://stackoverflow.com/questions/1949066/java-lang-outofmemoryerror-bitmap-size-exceeds-vm-budget-android –

+0

그 다음 그것을 끝내고, 그것을 다시 시작하고 outofmemory해라. 나는 누출을 어디 선가 가지고 있다고 생각한다. – lelloman

+0

누출을 지적하면 감사하겠다. – UMAR

답변

1

사용하지 않을 때는 비트 맵을 재활용하십시오. 더 나은 성능을 얻으려면뷰 홀더를 사용하십시오. http://www.youtube.com/watch?v=wDBM6wVEO70. 나는 당신이 그 링크를 보길 제안한다. listview에 적용되는 것은 무엇이든간에 gridview에도 적용되며 비디오는 그것에 대해 이야기합니다. 비디오에는 또한 메모리 누수를 방지하기 위해 사용해야하는 뷰 홀더에 대한 이야기가 있습니다.

http://android-developers.blogspot.de/2009/01/avoiding-memory-leaks.html에서 메모리 누수가 발생하지 않도록하는 방법에 대해서도 설명합니다.

http://developer.android.com/training/displaying-bitmaps/load-bitmap.html. 축소 된 버전을 메모리에로드

메모리 누수를 확인하려면 MAT 분석기를 사용하십시오. http://www.youtube.com/watch?v=_CruQY55HOk.

http://developer.android.com/training/articles/perf-tips.html에서 몇 가지 팁을 고려하십시오.

+0

라그 난단에게 감사드립니다. 자세한 답변을 얻었으므로이 문제를 해결하는 데 많은 도움이되었습니다. – UMAR

+0

도움이 되니 기쁩니다. 당신은 28 이미지를 표시합니다. 일부 앱에는 더 많은 기능이 있습니다. 따라서 28 개의 이미지를 표시해서는 메모리 오류가 발생하지 않습니다. 이들을 효율적으로로드하면 메모리가 부족하지 않아야합니다. – Raghunandan

1

(28) 이미지가 약 ~ 4 메가 ​​바이트 RAM입니다. 플러스 응용 프로그램 데이터 및 작은 힙에 맞지 않습니다. 당신은 large heap into manifest를 설정할 수 있습니다 :

android:largeHeap="true" 

그러나이 방법은 다시이 오류가 나오긴 수있는 무제한의 메모리와 이미지의 증가가 있기 때문에, 해결 방법으로 볼 수 있습니다. 또한 장치 화면 크기에 따라 이미지를 느슨하게로드하거나 크기를 조정해야합니다.

+0

http://www.youtube.com/watch?v=_CruQY55HOk를 호출하면됩니다. 비디오에서, 사람들은 android : largeHeap = "true"에 대한 경고를줍니다. 왜냐하면 큰 힙을 필요로하지 않기 때문에 이것을 사용하는 것입니다. 힙 크기가 많을수록 garbabge 컬렉션이 자주 발생합니다. – Raghunandan

+1

맞습니다. 큰 힙은 해결책이 아닙니다. 링크를 가져 주셔서 감사합니다. – neworld

+0

우수 답변 나는 비슷한 문제를 겪었고 (12 개의 이미지에 대해 ~ 5 MB를 할당하려고 시도했다.) 몇 시간 동안 그것을 해결할 수 없었다. 이 매개 변수는 내가 필요한 것입니다. – Alexey

0

느린 스크롤의 이유는 아주 간단합니다. 보기가 생성 될 때마다 UI 스레드에서 이미지를로드하고 있습니다. 우선 순위가 낮은 다른 스레드에로드를 위임해야합니다. 원하는 경우 UI 스레드에 축소판 그림을로드하여 신속하게 무언가를 표시 한 다음 백그라운드에서 전체 해상도를로드 할 수 있습니다.

Android는 앱을 멋지게 만드는 많은 트릭을 가지고 있지만 현명하게 사용해야합니다. 예를 들어 안드로이드는 드로잉 캐시 (Drawing Cache)라고 불리는 정적 뷰를 캐시하지만 ImgaeViews의 경우에는 추가 메모리가 필요하고 아무 것도주지 않기 때문에 무의미합니다. 하드웨어 가속 UI를 사용하면 각보기 캐시가 2의 2 진수로 그려 지므로 더 많은 메모리가 사용됩니다. 즉, 100x35px 버튼은 128x64x4 바이트의 추가 메모리를 차지합니다. 안드로이드는 선형 텍스쳐 샘플러와 같이 어떤 종류의 앤티 앨리어싱을 사용하려고 시도합니다. 멋지지만 CPU 시간이 많이 걸리므로 해제해야 할 수 있습니다.

setImageResource를 통해 이미지를로드하면 거의 제어 할 수 없습니다.좀 더 정확하게로드 및 언로드를 제어 할 수 있도록 이미지를로드 할 수 있습니다. 이미지를 조금 캐시 할 수도 있습니다. LRU 캐시는 이러한 용도로 만들어진 클래스의 좋은 예입니다 : http://developer.android.com/reference/android/util/LruCache.html. 현재 이미지를로드하고 왼쪽과 오른쪽에 하나씩 미리로드 할 수 있습니다. 사용자가 이전 이미지로 돌아 가면 메모리에 저장됩니다.

또한 무차별 대항력을 사용하려는 경우 NativeBuffer : http://code.google.com/p/native-buffer/을 사용하여 이미지를 캐싱 할 수 있습니다. 갤러리를 재 설계해야하지만 이미지가 많은 앱을 많이 서두를 수 있습니다.

관련 문제