2014-02-10 5 views
-1

У меня часто возникают ошибки памяти в моем приложении. Я считаю, что это связано с растровыми изображениями, которые я загружаю с сервера. Любые идеи почему?Android: ошибка памяти при использовании растровых изображений

**A method in my activity that sets up ListView:** 

private class NewsFeedArrayAdapter extends ArrayAdapter<AnimalLocationLog> { 

    ArrayList<AnimalLocationLog> objects; 
    Context context; 
    ArrayList<String> urls; 
    ImageDownloader downloader;  

    public NewsFeedArrayAdapter(Context context, int textViewResourceId, ArrayList<AnimalLocationLog> objects, ArrayList<String> urls) { 
     super(context, textViewResourceId, objects); 
     this.context = context; 
     this.objects = objects; 
     this.urls = urls; 
     downloader = new ImageDownloader(); 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     View rowView = inflater.inflate(R.layout.list_single, parent, false); 

     AnimalLocationLog current = objects.get(position); 

     ImageView image = (ImageView) rowView.findViewById(R.id.icon); 
     TextView firstline = (TextView) rowView.findViewById(R.id.firstline); 
     TextView secondline = (TextView) rowView.findViewById(R.id.secondline); 

     // Download external images 
     downloader.download(urls.get(position % 14), image); 

     firstline.setText(current.getSpecies()); 
     secondline.setText("Spotted " + current.getDateTime().toString("yyyy-MM-dd H:m")); 

     return rowView; 
    } 


**ImageDownloader.java:** 

    public class ImageDownloader { 

     Map<String,Bitmap> imageCache; 

     public ImageDownloader(){ 
      imageCache = new HashMap<String, Bitmap>(); 

     } 

     //download function 
     public void download(String url, ImageView imageView) { 
      if (cancelPotentialDownload(url, imageView)) { 

       //Caching code right here 
       String filename = String.valueOf(url.hashCode()); 
       File f = new File(getCacheDirectory(imageView.getContext()), filename); 

        // Is the bitmap in our memory cache? 
       Bitmap bitmap = null; 

        bitmap = (Bitmap)imageCache.get(f.getPath()); 

        if(bitmap == null){ 

         bitmap = BitmapFactory.decodeFile(f.getPath()); 

         if(bitmap != null){ 
          imageCache.put(f.getPath(), bitmap); 
         } 

        } 
        //No? download it 
        if(bitmap == null){ 
         BitmapDownloaderTask task = new BitmapDownloaderTask(imageView); 
         DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task); 
         imageView.setImageDrawable(downloadedDrawable); 
         task.execute(url); 
        }else{ 
         //Yes? set the image 
         imageView.setImageBitmap(bitmap); 
        } 
      } 
     } 

     //cancel a download (internal only) 
     private static boolean cancelPotentialDownload(String url, ImageView imageView) { 
      BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView); 

      if (bitmapDownloaderTask != null) { 
       String bitmapUrl = bitmapDownloaderTask.url; 
       if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) { 
        bitmapDownloaderTask.cancel(true); 
       } else { 
        // The same URL is already being downloaded. 
        return false; 
       } 
      } 
      return true; 
     } 

     //gets an existing download if one exists for the imageview 
     private static BitmapDownloaderTask getBitmapDownloaderTask(ImageView imageView) { 
      if (imageView != null) { 
       Drawable drawable = imageView.getDrawable(); 
       if (drawable instanceof DownloadedDrawable) { 
        DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable; 
        return downloadedDrawable.getBitmapDownloaderTask(); 
       } 
      } 
      return null; 
     } 

     //our caching functions 
     // Find the dir to save cached images 
     private static File getCacheDirectory(Context context){ 
      String sdState = android.os.Environment.getExternalStorageState(); 
      File cacheDir; 

      if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) { 
       File sdDir = android.os.Environment.getExternalStorageDirectory(); 

       //TODO : Change your diretcory here 
       cacheDir = new File(sdDir,"data/tac/imagess"); 
      } 
      else 
       cacheDir = context.getCacheDir(); 

      if(!cacheDir.exists()) 
       cacheDir.mkdirs(); 
       return cacheDir; 
     } 

     private void writeFile(Bitmap bmp, File f) { 
       FileOutputStream out = null; 

       try { 
       out = new FileOutputStream(f); 
       bmp.compress(Bitmap.CompressFormat.PNG, 80, out); 
       } catch (Exception e) { 
       e.printStackTrace(); 
       } 
       finally { 
       try { if (out != null) out.close(); } 
       catch(Exception ex) {} 
       } 
     } 
     /////////////////////// 

     //download asynctask 
     public class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> { 
      private String url; 
      private final WeakReference<ImageView> imageViewReference; 

      public BitmapDownloaderTask(ImageView imageView) { 
       imageViewReference = new WeakReference<ImageView>(imageView); 
      } 

      @Override 
      // Actual download method, run in the task thread 
      protected Bitmap doInBackground(String... params) { 
       // params comes from the execute() call: params[0] is the url. 
       url = (String)params[0]; 
       return downloadBitmap(params[0]); 
      } 

      @Override 
      // Once the image is downloaded, associates it to the imageView 
      protected void onPostExecute(Bitmap bitmap) { 
       if (isCancelled()) { 
        bitmap = null; 
       } 

       if (imageViewReference != null) { 
        ImageView imageView = imageViewReference.get(); 
        BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView); 
        // Change bitmap only if this process is still associated with it 
        if (this == bitmapDownloaderTask) { 
         imageView.setImageBitmap(bitmap); 

         //cache the image 


         String filename = String.valueOf(url.hashCode()); 
         File f = new File(getCacheDirectory(imageView.getContext()), filename); 

         imageCache.put(f.getPath(), bitmap); 

         writeFile(bitmap, f); 
        } 
       } 
      } 


     } 

     static class DownloadedDrawable extends ColorDrawable { 
      private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference; 

      public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) { 
       super(Color.BLACK); 
       bitmapDownloaderTaskReference = 
        new WeakReference<BitmapDownloaderTask>(bitmapDownloaderTask); 
      } 

      public BitmapDownloaderTask getBitmapDownloaderTask() { 
       return bitmapDownloaderTaskReference.get(); 
      } 
     } 

     //the actual download code 
     static Bitmap downloadBitmap(String url) { 
      HttpParams params = new BasicHttpParams(); 
      params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1); 
      HttpClient client = new DefaultHttpClient(params); 
      final HttpGet getRequest = new HttpGet(url); 

      try { 
       HttpResponse response = client.execute(getRequest); 
       final int statusCode = response.getStatusLine().getStatusCode(); 
       if (statusCode != HttpStatus.SC_OK) { 
        Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url); 
        return null; 
       } 

       final HttpEntity entity = response.getEntity(); 
       if (entity != null) { 
        InputStream inputStream = null; 
        try { 
         inputStream = entity.getContent(); 
         final Bitmap bitmap = BitmapFactory.decodeStream(inputStream); 
         return bitmap; 
        } finally { 
         if (inputStream != null) { 
          inputStream.close(); 
         } 
         entity.consumeContent(); 
        } 
       } 
      } catch (Exception e) { 
       // Could provide a more explicit error message for IOException or IllegalStateException 
       getRequest.abort(); 
       Log.w("ImageDownloader", "Error while retrieving bitmap from " + url + e.toString()); 
      } finally { 
       if (client != null) { 
        //client.close(); 
       } 
      } 
      return null; 
     } 
    } 
+2

Используйте [эти руководящие принципы] (http://developer.android.com /training/displaying-bitmaps/load-bitmap.html). Если это не поможет, выполните поиск stackoverflow для вашего вопроса. Об этом много вопросов. – Sam

ответ

1

Если у вас есть изображение с высоким разрешением, его следует уменьшить. См. Раздел «Загрузка масштабированной версии в память».
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
Out of memory error on Android

О том, как избежать их:
How to avoid an out of memory error while using bitmaps in Android

Для oveview:
http://blogs.innovationm.com/android-out-of-memory-error-causes-solution-and-best-practices/ http://android-developers.blogspot.de/2009/01/avoiding-memory-leaks.html

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