2016-05-10 3 views
0

Ну, через 2 дня я борюсь, пожалуйста, помогите мне решить эту проблему.Загрузка изображений с SDK в gridview, выбрасывание исключения из памяти?

Я хочу загрузить список всех изображений во внешнем хранилище в мое 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», где вы можете (см. 'InBitmap' из' BitmapFactory.Options'). Разрешить объекты «Bitmap» собирать мусор, когда они больше не нужны и не могут быть переработаны. – CommonsWare

+0

Восстановить объекты Bitmap? Можете ли вы дать ссылку на ссылку или объяснить, как ее решить? – 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

п всегда возвращается как 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 поможет вам сэкономить вам кучу кода и времени.

Вы можете сделать что-то подобное из вашего фрагмента или 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

Picasso не поможет мне, так как я уже пробовал, и изображения, которыми я занимаюсь, являются локальными изображениями SD-карт и огромны в количестве – Manikanta

+0

Не знаете, почему это не поможет, предоставленные мной фрагменты кода позволяют вам давать Местоположение файла Picasso с вашей локальной SD-карты: Picasso.with (context) .load (новый файл (...)). В (imageView3); Picasso помогает вам загружать их по мере необходимости, а не сразу. – shredder

+0

Я использовал picasso, так что мои последние проекты Android для загрузки url, но не уверены, может ли он помочь мне в загрузке локальных изображений, и я попробовал загружать изображение в свой адаптер onBindHolder(), но так как он находится на моем основном потоке, он висит так, что любое решение ? – Manikanta

0

Я использую следующий метод для получения растрового изображения, который уменьшенный не бросать исключения OOM:

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, и я сохраняю размер экрана в пикселях, как только приложение запускается.

Смежные вопросы