1

我有兩個活動。在開始活動中有小圖片。點擊其中的每一個,然後使用圖庫在ViewPager處打開其他活動。加載圖像時發生應用程序崩潰(java.lang.OutOfMemoryError)

當打開圖庫時,它完美地滑動圖像沒有任何問題。

但是當我回到開始活動並重新打開庫,應用與 java.lang.OutOfMemoryError位圖大小墜毀超過VM預算

我試圖重新大小的圖像,得到它的規模較小,但它並不能幫助。它也墜毀了,但稍晚一點。

我認爲當與畫廊和所有圖像的活動沒有被破壞。它有內存泄漏。

對於圖庫我用AndroidTouchGallerylink

這是示例應用程序使用此代碼:工作區link on GoogleDrive

我的代碼。 啓動活動

public class MainActivity extends Activity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 


     ArrayList<String> list_big_images = new ArrayList<String>(); 
     list_big_images.add("http://www.oa.edu.ua/assets/images/n/2013/small/evropeyska_misiya1_s.jpg"); 
     list_big_images.add("http://www.oa.edu.ua/assets/images/n/2013/small/evropeyska_misiya2_s.jpg"); 
     list_big_images.add("http://www.oa.edu.ua/assets/images/n/2013/small/evropeyska_misiya3_s.jpg"); 

     ArrayList<String> list_big_images_big = new ArrayList<String>(); 
     list_big_images_big.add("http://www.oa.edu.ua/assets/images/n/2013/big/evropeyska_misiya1_b.jpg"); 
     list_big_images_big.add("http://www.oa.edu.ua/assets/images/n/2013/big/evropeyska_misiya2_b.jpg"); 
     list_big_images_big.add("http://www.oa.edu.ua/assets/images/n/2013/big/evropeyska_misiya3_b.jpg");  


     //get Screen size 
     int width; //Display width 
     int height; //Display height 

     if ( Integer.valueOf(android.os.Build.VERSION.SDK_INT) > 13) { 
       Display display = getWindowManager().getDefaultDisplay(); 
        Point size = new Point(); 
        display.getSize(size); 
        width = size.x; 
        height = size.y; 
     } else { 
      Display display = getWindowManager().getDefaultDisplay(); 
      width = display.getWidth(); 
      height = display.getHeight(); 
     } 

     ImageView[] imageViewArray = new ImageView[list_big_images.size()]; 
     for (int i = 0; i<list_big_images.size(); i++) 
      try { 
        String url = list_big_images.get(i); 
        //url_img_small.add(text); 
        // Let's create the missing ImageView 
        imageViewArray[i] = new ImageView(MainActivity.this);        

        // Now the layout parameters, these are a little tricky at first 
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(width/3, width/3); 
        imageViewArray[i].setScaleType(ImageView.ScaleType.FIT_XY); 
        imageViewArray[i].setId(i + 1); // BELOW id 0 doesn't work 
        imageViewArray[i].setPadding(0, 5, 5, 0); 
        if (i > 0) { 
         if (i % 3 == 0){ 
          params.addRule(RelativeLayout.BELOW, imageViewArray[i - 3].getId()); 
         } 
         else { 
          params.addRule(RelativeLayout.RIGHT_OF, imageViewArray[i - 1].getId()); 
          if (i>2) 
           params.addRule(RelativeLayout.BELOW, imageViewArray[i - 3].getId()); 
         }; 
        } 

        Drawable drawable = grabImageFromUrl(url); 
        imageViewArray[i].setImageDrawable(drawable); 

        final ArrayList<String> list_big_images_big2 = list_big_images_big; 
        final int pos = i; 
        imageViewArray[i].setOnClickListener(new OnClickListener() 

         { 
          @Override 
          public void onClick(View v) { 
           System.out.println(v.getId()); 
           Intent intent = new Intent(v.getContext(), Full_Image_Activity.class); 
           intent.putExtra("ArrayImgBig", list_big_images_big2); 
           intent.putExtra("pos", pos+1); 
           startActivityForResult(intent, 0); 

          } 
         }); 

        // Let's get the root layout and add our ImageView 
        RelativeLayout layout = (RelativeLayout) findViewById(R.id.moreImages); 
        layout.addView(imageViewArray[i], params); 
       } 
       catch (Exception e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
     } 

    //load Image from Url 
    private Drawable grabImageFromUrl(String url) throws Exception { 
     return Drawable.createFromStream(
       (InputStream) new URL(url).getContent(), "src"); 
    } 


} 

它`活動與畫廊

public class Full_Image_Activity extends Activity { 

    ArrayList <String> ArrayImgBig = null; 
    int id_news; 
    private GalleryViewPager mViewPager; 
    int pos ; //Picture Position 
    UrlPagerAdapter pagerAdapter; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_full__image); 

     ArrayImgBig = getIntent().getExtras().getStringArrayList("ArrayImgBig"); 
     pos = getIntent().getExtras().getInt("pos"); 

     UrlPagerAdapter pagerAdapter = new UrlPagerAdapter(Full_Image_Activity.this, ArrayImgBig); 
     pagerAdapter.setOnItemChangeListener(new OnItemChangeListener() 
     { 
      @Override 
      public void onItemChange(int currentPosition) 
      { 
       Toast.makeText(Full_Image_Activity.this, "Current item is " + currentPosition, Toast.LENGTH_SHORT).show(); 
      } 


     }); 

     mViewPager = (GalleryViewPager)findViewById(R.id.viewer); 
     mViewPager.setOffscreenPageLimit(3); 
     mViewPager.setAdapter(pagerAdapter); 
     mViewPager.setCurrentItem(pos); 
    } 


    @Override 
    public void onBackPressed() { 
     this.finish(); 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     pagerAdapter = null; 
     mViewPager = null; 
     System.gc(); 
    } 
} 

我使用的方法onDestoy。但它沒有幫助。一切都是一樣的。

日誌:

11-27 15:39:59.239: I/System.out(471): 1 
11-27 15:40:00.248: D/dalvikvm(471): GC_EXTERNAL_ALLOC freed 1638K, 48% free 4736K/9031K, external 15372K/16229K, paused 116ms 
11-27 15:40:00.879: D/dalvikvm(471): GC_EXTERNAL_ALLOC freed 35K, 48% free 4742K/9031K, external 17773K/18518K, paused 100ms 
11-27 15:40:02.519: I/dalvikvm(471): Jit: resizing JitTable from 2048 to 4096 
11-27 15:40:04.959: W/KeyCharacterMap(471): No keyboard for id 0 
11-27 15:40:04.959: W/KeyCharacterMap(471): Using default keymap: /system/usr/keychars/qwerty.kcm.bin 
11-27 15:40:05.159: D/dalvikvm(471): GC_EXPLICIT freed 155K, 49% free 4654K/9031K, external 20410K/21124K, paused 111ms 
11-27 15:40:05.738: D/dalvikvm(471): GC_EXPLICIT freed 3K, 49% free 4652K/9031K, external 20410K/21124K, paused 223ms 
11-27 15:40:10.703: I/System.out(471): 2 
11-27 15:40:11.748: D/dalvikvm(471): GC_EXTERNAL_ALLOC freed 43K, 48% free 4754K/9031K, external 20410K/21124K, paused 106ms 
11-27 15:40:11.998: D/dalvikvm(471): GC_EXTERNAL_ALLOC freed 4K, 48% free 4780K/9031K, external 23046K/23760K, paused 112ms 
11-27 15:40:12.048: E/dalvikvm-heap(471): 1334000-byte external allocation too large for this process. 
11-27 15:40:12.208: E/GraphicsJNI(471): VM won't let us allocate 1334000 bytes 
11-27 15:40:12.208: D/dalvikvm(471): GC_FOR_MALLOC freed 0K, 48% free 4780K/9031K, external 23046K/23760K, paused 87ms 
11-27 15:40:12.229: D/skia(471): --- decoder->decode returned false 
11-27 15:40:12.238: W/dalvikvm(471): threadid=23: thread exiting with uncaught exception (group=0x40015560) 
11-27 15:40:12.248: E/AndroidRuntime(471): FATAL EXCEPTION: AsyncTask #5 
11-27 15:40:12.248: E/AndroidRuntime(471): java.lang.RuntimeException: An error occured while executing doInBackground() 
11-27 15:40:12.248: E/AndroidRuntime(471): at android.os.AsyncTask$3.done(AsyncTask.java:200) 
11-27 15:40:12.248: E/AndroidRuntime(471): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274) 
11-27 15:40:12.248: E/AndroidRuntime(471): at java.util.concurrent.FutureTask.setException(FutureTask.java:125) 
11-27 15:40:12.248: E/AndroidRuntime(471): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308) 
11-27 15:40:12.248: E/AndroidRuntime(471): at java.util.concurrent.FutureTask.run(FutureTask.java:138) 
11-27 15:40:12.248: E/AndroidRuntime(471): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088) 
11-27 15:40:12.248: E/AndroidRuntime(471): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581) 
11-27 15:40:12.248: E/AndroidRuntime(471): at java.lang.Thread.run(Thread.java:1019) 
11-27 15:40:12.248: E/AndroidRuntime(471): Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget 
11-27 15:40:12.248: E/AndroidRuntime(471): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method) 
11-27 15:40:12.248: E/AndroidRuntime(471): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:470) 
11-27 15:40:12.248: E/AndroidRuntime(471): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:525) 
11-27 15:40:12.248: E/AndroidRuntime(471): at ru.truba.touchgallery.TouchView.UrlTouchImageView$ImageLoadTask.doInBackground(UrlTouchImageView.java:102) 
11-27 15:40:12.248: E/AndroidRuntime(471): at ru.truba.touchgallery.TouchView.UrlTouchImageView$ImageLoadTask.doInBackground(UrlTouchImageView.java:1) 
11-27 15:40:12.248: E/AndroidRuntime(471): at android.os.AsyncTask$2.call(AsyncTask.java:185) 
11-27 15:40:12.248: E/AndroidRuntime(471): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306) 
11-27 15:40:12.248: E/AndroidRuntime(471): ... 4 more 
+0

可能的重複[加載圖像到Bitmap對象時出現內存不足的問題](http://stackoverflow.com/questions/477572/strange-out-of-memory - 正在加載圖像到位圖 - 對象) – tcooc

回答

0

編輯您的onDestroy以下幾點:

@Override 
public void onDestroy() { 
    pagerAdapter = null; 
    mViewPager = null; 
    System.gc(); 
    super.onDestroy(); 
} 

或把代碼放到的onPause()

+0

嘗試編輯onDrestroy並嘗試使用onPause()。但我有同樣的錯誤。更新問題。添加錯誤日誌。 – Volodymyr

0

我會建議你使用Universal Image Loader庫,您可以阻止您的應用程序出現java.lang.OutOfMemoryError錯誤。這裏是github link。看一下這個。

另外,如果不再使用,您可以回收位圖對象。您不需要撥打System.gc()以釋放內存。如果你想釋放內存,你應該調用recycle()方法。

另一方面,還有一種方法可以避免這種例外。您可以重新採樣圖像。在前面的線程中解釋了這種方式。這裏是link

希望這可以幫助!

0

你可以在你的viewpager適配器中檢查你是否覆蓋了destroyItem。這將在屏幕上不再可見時刪除視圖,從而釋放爲該圖像分配的內存。

例如:

@Override 
    public void destroyItem(ViewGroup container, int position, Object object) { 
     container.removeView((View) object); 
    } 

我也建議你使用像Picasso或通用圖像加載器的ImageLoader的加載圖像異步關閉UI線程,並在爲您處理,所以你不要」內存及其分配t出內存異常...

相關問題