2016-05-10 3 views
0

2日から私は苦労しています。誰かがこの問題を解決するのを助けてください。イメージをsdcardからgridview throwに読み込むメモリ不足例外をスローしますか?

外部ストレージ内のすべてのイメージのリストをmy gridviewにロードします。

この方法を使用して、システムから画像のリストを取得することができました。

public static ArrayList<String> getFilePaths(Activity context) 
    { 


     Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; 
     String[] projection = {MediaStore.Images.ImageColumns.DATA}; 
     Cursor c = null; 
     SortedSet<String> dirList = new TreeSet<String>(); 
     ArrayList<String> resultIAV = new ArrayList<String>(); 

     String[] directories = null; 
     if (u != null) 
     { 
      c = context.managedQuery(u, projection, null, null, null); 
     } 

     if ((c != null) && (c.moveToFirst())) 
     { 
      do 
      { 
       String tempDir = c.getString(0); 
       tempDir = tempDir.substring(0, tempDir.lastIndexOf("/")); 
       try{ 
        dirList.add(tempDir); 
       } 
       catch(Exception e) 
       { 

       } 
      } 
      while (c.moveToNext()); 
      directories = new String[dirList.size()]; 
      dirList.toArray(directories); 

     } 

     for(int i=0;i<dirList.size();i++) 
     { 
      File imageDir = new File(directories[i]); 
      File[] imageList = imageDir.listFiles(); 
      if(imageList == null) 
       continue; 
      for (File imagePath : imageList) { 
       try { 

        if(imagePath.isDirectory()) 
        { 
         imageList = imagePath.listFiles(); 

        } 
        if (imagePath.getName().contains(".jpg")|| imagePath.getName().contains(".JPG") 
          || imagePath.getName().contains(".jpeg")|| imagePath.getName().contains(".JPEG") 
          || imagePath.getName().contains(".png") || imagePath.getName().contains(".PNG") 
          || imagePath.getName().contains(".gif") || imagePath.getName().contains(".GIF") 
          || imagePath.getName().contains(".bmp") || imagePath.getName().contains(".BMP") 
          ) 
        { 



         String path= imagePath.getAbsolutePath(); 
         resultIAV.add(path); 

        } 
       } 
       // } 
       catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     } 

     return resultIAV; 


    } 

は今、トリッキーな部分は、私はそれが多くのメモリを食べるように、実際の画像をロードし、最終的にはそれゆえbitmap Outofmemory exceptionを取得する私は、別の画像の読み込みを実行エグゼキュータで画像ローダを持つことができないことを知って、来スレッドと画像を非同期的にロードするのは画像ローダです。ここ

public class AbstractImageLoader { 
    private static ExecutorService executorService; 
    private static AbstractImageLoader loader; 
    public static int maxWidth; 
    Handler handler;; 
    private Map<ImageView,String> imageViews; 

    static { 
     AbstractImageLoader.executorService = Executors.newFixedThreadPool(5); 
    } 

    public AbstractImageLoader(final Context context) { 
     this.imageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>()); 
     this.handler = new Handler(); 
     AbstractImageLoader.maxWidth = context.getResources().getDisplayMetrics().widthPixels/3; 
    } 

    public static AbstractImageLoader getInstance(final Context context) { 
     if (AbstractImageLoader.loader == null) { 
      AbstractImageLoader.loader = new AbstractImageLoader(context); 
     } 
     return AbstractImageLoader.loader; 
    } 

    private void queuePhoto(final String s, final ImageView imageView, final int n) { 
     AbstractImageLoader.executorService.submit(new PhotosLoader(new PhotoToLoad(s, imageView, n))); 
    } 

    public void DisplayImage(final String s, final ImageView imageView) { 
     this.DisplayImage(s, imageView, -1); 
    } 

    public void DisplayImage(final String s, final ImageView imageView, final int imageResource) { 
     this.imageViews.put(imageView, s); 
     final Bitmap value = MemCache.get(s); 
     if (value != null) { 
      imageView.setImageBitmap(value); 
      return; 
     } 
     this.queuePhoto(s, imageView, imageResource); 
     if (imageResource > -1) { 
      imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); 
      imageView.setImageResource(imageResource); 
      return; 
     } 
     imageView.setImageDrawable((Drawable)null); 
    } 

    public void DisplayImage(final String s, final ImageView imageView, final Drawable imageDrawable) { 
     this.imageViews.put(imageView, s); 
     final Bitmap value = MemCache.get(s); 
     if (value != null) { 
      imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); 
      imageView.setImageBitmap(value); 
     } 
     else { 
      this.queuePhoto(s, imageView, -1); 
      if (imageDrawable != null) { 
       imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); 
       imageView.setImageDrawable(imageDrawable); 
      } 
     } 
    } 

    public void clearCache() { 
     MemCache.clear(); 
    } 

    public void delete(final String s) { 
     MemCache.remove(s); 
    } 

    protected Bitmap getBitmap(final String ex) { 
     final Bitmap bitmap = null; 


     final File file = new File((String)ex); 
     if (!file.exists()) { 
      final String[] list = file.getParentFile().list(new FileUtils$Filters$6()); 
      Object o = bitmap; 
      if (list != null) { 
       if (list.length != 0) { 
        o = new File(file.getParent(), list[0]); 
        final String absolutePath = ((File)o).getAbsolutePath(); 
        o = ThumbUtils.getThumbnail(absolutePath, AlbumViewLoader.maxWidth); 
        return ThumbUtils.getThumbnail((String)ex, AlbumViewLoader.maxWidth); 
       } 
       o = bitmap; 
      } 
      return (Bitmap)o; 
     } 
     return ThumbUtils.getThumbnail((String)ex, AlbumViewLoader.maxWidth); 
    } 

    boolean imageViewReused(final PhotoToLoad photoToLoad) { 
     final String s = imageViews.get(photoToLoad.imageView); 
     return s == null || !s.equals(photoToLoad.url); 
    } 

    class BitmapDisplayer implements Runnable 
    { 
     Bitmap bitmap; 
     PhotoToLoad photoToLoad; 

     public BitmapDisplayer(final Bitmap bitmap, final PhotoToLoad photoToLoad) { 
      this.bitmap = bitmap; 
      this.photoToLoad = photoToLoad; 
     } 

     @Override 
     public void run() { 
      if (!AbstractImageLoader.this.imageViewReused(this.photoToLoad)) { 
       if (this.bitmap != null) { 
        this.photoToLoad.imageView.setImageBitmap(this.bitmap); 
        this.photoToLoad.imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); 
        return; 
       } 
       if (this.photoToLoad.placeholder_stub > -1) { 
        this.photoToLoad.imageView.setImageResource(this.photoToLoad.placeholder_stub); 
        this.photoToLoad.imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); 
       } 
      } 
     } 
    } 

    private class PhotoToLoad 
    { 
     public ImageView imageView; 
     public int placeholder_stub; 
     public String url; 

     public PhotoToLoad(final String url, final ImageView imageView, final int placeholder_stub) { 
      this.url = url; 
      this.imageView = imageView; 
      this.placeholder_stub = placeholder_stub; 
     } 
    } 

    class PhotosLoader implements Runnable 
    { 
     PhotoToLoad photoToLoad; 

     PhotosLoader(final PhotoToLoad photoToLoad) { 
      this.photoToLoad = photoToLoad; 
     } 

     @Override 
     public void run() { 
      try { 
      /* if (!imageViewReused(this.photoToLoad)) { 
        return; 
       }*/ 
       final Bitmap bitmap = AbstractImageLoader.this.getBitmap(this.photoToLoad.url); 
       if (bitmap != null) { 
        MemCache.put(this.photoToLoad.url, bitmap); 
       } 

        AbstractImageLoader.this.handler.post((Runnable)new BitmapDisplayer(bitmap, this.photoToLoad)); 

      } 
      catch (Throwable t) { 
       t.printStackTrace(); 
      } 
     } 
    } 
} 

は、ビットマップを作成し、私のユーティリティクラスです。だからここ

public static Bitmap getThumbnail(final String s, int n) { 
     final BitmapFactory.Options bitmapFactory$Options = new BitmapFactory.Options(); 
     bitmapFactory$Options.inSampleSize = 1; 
     bitmapFactory$Options.inJustDecodeBounds = true; 
     BitmapFactory.decodeFile(s, bitmapFactory$Options); 
     if (bitmapFactory$Options.mCancel || bitmapFactory$Options.outWidth == -1 || bitmapFactory$Options.outHeight == -1) { 
      return null; 
     } 
     final int outHeight = bitmapFactory$Options.outHeight; 
     final int outWidth = bitmapFactory$Options.outWidth; 
     final float max = Math.max(n/outWidth, n/outHeight); 
     n = (int)(outWidth * max); 
     final int n2 = (int)(outHeight * max); 
     bitmapFactory$Options.inSampleSize = calculateInSampleSize(bitmapFactory$Options, n, n); 
     bitmapFactory$Options.inJustDecodeBounds = false; 
     bitmapFactory$Options.inDither = true; 
     bitmapFactory$Options.inPreferredConfig = Bitmap.Config.RGB_565; 
     Bitmap bmp = BitmapFactory.decodeFile(s, bitmapFactory$Options); 
     return ThumbnailUtils.extractThumbnail(bmp, n, n, 2); 
    } 

は私の質問です:私のサムネイルユーティリティメソッド1.In

この計算:

final float max = Math.max(n/outWidth, n/outHeight); 
      n = (int)(outWidth * max); 
      final int n2 = (int)(outHeight * max); 

nは常に0として返されるため、サムネイルはロードされていないので、時間が経過すると212にハードコードされますサムネイル負荷が

を開始した。しかし、画像の特定の数をロードした後、私はまだここにout of memory exception

を取得していますlogcatです:

java.lang.OutOfMemoryError: Failed to allocate a 347790 byte allocation with 294944 free bytes and 288KB until OOM 
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err:  at dalvik.system.VMRuntime.newNonMovableArray(Native Method) 
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err:  at android.graphics.BitmapFactory.nativeDecodeStream(Native Method) 
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err:  at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:639) 
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err:  at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:615) 
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err:  at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:391) 
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err:  at com.geekmk.audiofx.test.ThumbUtils.getThumbnail(ThumbUtils.java:66) 
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err:  at com.geekmk.audiofx.test.AbstractImageLoader.getBitmap(AbstractImageLoader.java:110) 
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err:  at com.geekmk.audiofx.test.AbstractImageLoader$PhotosLoader.run(AbstractImageLoader.java:171) 
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err:  at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422) 
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err:  at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err:  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err:  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err:  at java.lang.Thread.run(Thread.java:818) 

私に事前に 感謝を助けてください。

+0

本当にヒープスペースを使い切っています。画像の読み込みが少なくなります。 'Bitmap'オブジェクトをリサイクルすることができます(' BitmapFactory.Options'の 'inBitmap'を参照してください)。 'Bitmap'オブジェクトは不要になったときにガベージコレクションされ、リサイクルできません。 – CommonsWare

+0

ビットマップオブジェクトを再作成しますか?あなたは私に参照リンクを与えたり、これに取り組む方法を説明できますか? – Manikanta

+0

http://developer.android.com/training/displaying-bitmaps/manage-memory.html http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inBitmap – CommonsWare

答えて

0

nは常に0として返されるので、サムネイルがロードされて取得されていないので、 は時間のために私は212にそれをハードコードされているサムネイルの読み込みを使用すると、int型のを混合し、フロートのされているためです

を開始しました。フロートを使用するようにこのコードを変更してみてください。

public static Bitmap getThumbnail(final String s, float n) { 

final float outHeight = bitmapFactory$Options.outHeight; 
final float outWidth = bitmapFactory$Options.outWidth; 

わからない

あなたがそこに、最終的な使用している理由は、私はそれが必要だとは思いません。

Picassoのようなものを使用すると、たくさんのコードと時間を節約できます。

あなたは、私がOOM例外をスローしないように縮小されたビットマップを取得するため、以下の方法を使用し、あなたのフラグメントまたはViewHolder

Picasso.with(context).load(R.drawable.landing_screen).into(imageView1); 
Picasso.with(context).load("file:///android_asset/DvpvklR.png").into(imageView2); 
Picasso.with(context).load(new File(...)).into(imageView3); 
+0

ピカソは私がすでに手伝ってくれていて、私が扱っている画像はローカルのSDカードの画像であり、数字が巨大です。 – Manikanta

+0

私が提供したコードスニペットは、あなたのローカルSDカードからのピカソファイルの場所:Picasso.with(context).load(新しいファイル(...))。into(imageView3);ピカソは一度にすべてではなく、必要なときにそれらをロードするのに役立ちます。 – shredder

+0

私はピカソを使ってURLロードのための最後のアンドロイドプロジェクトを作成しましたが、ローカルイメージの読み込みに役立ち、アダプタのonBindHolder()で画像を読み込もうとしましたが、私のメインスレッドでは、 ? – Manikanta

0

からこのような何かを行うことができます。では

private static Bitmap getBitmapFromUri(@NonNull Context context, @NonNull Uri uri) throws IOException { 

     ParcelFileDescriptor parcelFileDescriptor = 
       context.getContentResolver().openFileDescriptor(uri, "r"); 
     assert parcelFileDescriptor != null; 
     FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor(); 
     Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor); 
     parcelFileDescriptor.close(); 

     TinyDB tinyDB = new TinyDB(context); 
     int maxSize = Math.min(tinyDB.getInt(AppConstants.DEVICE_WIDTH, 720), tinyDB.getInt(AppConstants.DEVICE_HEIGHT, 1080)); 
     int outWidth; 
     int outHeight; 
     int inWidth = image.getWidth(); 
     int inHeight = image.getHeight(); 
     if(inWidth > inHeight){ 
      outWidth = maxSize; 
      outHeight = (inHeight * maxSize)/inWidth; 
     } else { 
      outHeight = maxSize; 
      outWidth = (inWidth * maxSize)/inHeight; 
     } 

     return Bitmap.createScaledBitmap(image, outWidth, outHeight, false); 
    } 

をコードTinyDBは、SharedPreferencesのラッパーで、アプリの起動後すぐに画面サイズをピクセル単位で保存します。

関連する問題