2016-06-12 3 views
0

AsyncTask을 통해 여러 이미지를 다운로드하고 있습니다. 2-3 개의 이미지가있을 때 잘 작동합니다. 그러나 더 많은 이미지가있는 경우 많은 AsyncTask 인스턴스가 만들어져 오류가 발생합니다. 누구든지이 문제를 극복하는 방법을 알고 있습니까?AsyncTask 스레드에서 여러 이미지를 다운로드하면 오류가 발생합니다.

+0

이미지를 listview에로드하고 있습니까? – USKMobility

+0

오류 란 무엇인가요, 게시 Logtrace! –

+0

클래스의 철자법, 문법, 구문 및 이름입니다. – Ben

답변

0

여기에 코드를 추가해주십시오. 다운로드 "다음 사진"이렇게 시작하는) 기능을

protected void onPostExecute() { 
    doInBackground(); 
} 

또는 당신이 (당신의 onPostExecute에서 활동 기능을 트리거 할 수 있습니다

어쩌면 당신은 새와 같은을 시작합니다 AsyncTask를의 기능을 onPostExecute 사용하려고 할 수 있습니다 한 번에 하나의 asynctask 만 생성합니다. 안드로이드 문서에서

0

: 등의 ListView와의 GridView 이전 섹션에서 보여 으로 AsyncTask를 함께 사용하면 또 다른 문제를 소개하는 등의 일반적인 뷰 컴포넌트. 메모리를 효율적으로 사용하기 위해 이러한 구성 요소는 사용자가 스크롤 할 때 하위 뷰를 재활용합니다. 각 자식 뷰가 AsyncTask를 트리거하는 경우 이 완료되면 연결된 뷰가 다른 자식 뷰에서 사용을 위해 이미 재활용되지 않았다고 보장 할 수 없습니다. 또한 비동기 작업이 시작되는 순서가 의 순서대로 완료된다고 보장 할 수 없습니다.

Handle Concurrency

http://android-developers.blogspot.in/2010/07/multithreading-for-performance.html

public class ImageDownloader { 
     private static final String LOG_TAG = "ImageDownloader"; 

     public enum Mode { NO_ASYNC_TASK, NO_DOWNLOADED_DRAWABLE, CORRECT } 
     private Mode mode = Mode.NO_ASYNC_TASK; 

     /** 
     * Download the specified image from the Internet and binds it to the provided ImageView. The 
     * binding is immediate if the image is found in the cache and will be done asynchronously 
     * otherwise. A null bitmap will be associated to the ImageView if an error occurs. 
     * 
     * @param url The URL of the image to download. 
     * @param imageView The ImageView to bind the downloaded image to. 
     */ 
     public void download(String url, ImageView imageView) { 
      resetPurgeTimer(); 
      Bitmap bitmap = getBitmapFromCache(url); 

      if (bitmap == null) { 
       forceDownload(url, imageView); 
      } else { 
       cancelPotentialDownload(url, imageView); 
       imageView.setImageBitmap(bitmap); 
      } 
     } 

     /* 
     * Same as download but the image is always downloaded and the cache is not used. 
     * Kept private at the moment as its interest is not clear. 
      private void forceDownload(String url, ImageView view) { 
       forceDownload(url, view, null); 
      } 
     */ 

     /** 
     * Same as download but the image is always downloaded and the cache is not used. 
     * Kept private at the moment as its interest is not clear. 
     */ 
     private void forceDownload(String url, ImageView imageView) { 
      // State sanity: url is guaranteed to never be null in DownloadedDrawable and cache keys. 
      if (url == null) { 
       imageView.setImageDrawable(null); 
       return; 
      } 

      if (cancelPotentialDownload(url, imageView)) { 
       switch (mode) { 
        case NO_ASYNC_TASK: 
         Bitmap bitmap = downloadBitmap(url); 
         addBitmapToCache(url, bitmap); 
         imageView.setImageBitmap(bitmap); 
         break; 

        case NO_DOWNLOADED_DRAWABLE: 
         imageView.setMinimumHeight(156); 
         BitmapDownloaderTask task = new BitmapDownloaderTask(imageView); 
         task.execute(url); 
         break; 

        case CORRECT: 
         task = new BitmapDownloaderTask(imageView); 
         DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task); 
         imageView.setImageDrawable(downloadedDrawable); 
         imageView.setMinimumHeight(156); 
         task.execute(url); 
         break; 
       } 
      } 
     } 

     /** 
     * Returns true if the current download has been canceled or if there was no download in 
     * progress on this image view. 
     * Returns false if the download in progress deals with the same url. The download is not 
     * stopped in that case. 
     */ 
     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; 
     } 

     /** 
     * @param imageView Any imageView 
     * @return Retrieve the currently active download task (if any) associated with this imageView. 
     * null if there is no such task. 
     */ 
     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; 
     } 

     Bitmap downloadBitmap(String url) { 
      final int IO_BUFFER_SIZE = 4 * 1024; 

      // AndroidHttpClient is not allowed to be used from the main thread 
      final HttpClient client = (mode == Mode.NO_ASYNC_TASK) ? new DefaultHttpClient() : 
       AndroidHttpClient.newInstance("Android"); 
      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(); 
         // return BitmapFactory.decodeStream(inputStream); 
         // Bug on slow connections, fixed in future release. 
         return BitmapFactory.decodeStream(new FlushedInputStream(inputStream)); 
        } finally { 
         if (inputStream != null) { 
          inputStream.close(); 
         } 
         entity.consumeContent(); 
        } 
       } 
      } catch (IOException e) { 
       getRequest.abort(); 
       Log.w(LOG_TAG, "I/O error while retrieving bitmap from " + url, e); 
      } catch (IllegalStateException e) { 
       getRequest.abort(); 
       Log.w(LOG_TAG, "Incorrect URL: " + url); 
      } catch (Exception e) { 
       getRequest.abort(); 
       Log.w(LOG_TAG, "Error while retrieving bitmap from " + url, e); 
      } finally { 
       if ((client instanceof AndroidHttpClient)) { 
        ((AndroidHttpClient) client).close(); 
       } 
      } 
      return null; 
     } 

     /* 
     * An InputStream that skips the exact number of bytes provided, unless it reaches EOF. 
     */ 
     static class FlushedInputStream extends FilterInputStream { 
      public FlushedInputStream(InputStream inputStream) { 
       super(inputStream); 
      } 

      @Override 
      public long skip(long n) throws IOException { 
       long totalBytesSkipped = 0L; 
       while (totalBytesSkipped < n) { 
        long bytesSkipped = in.skip(n - totalBytesSkipped); 
        if (bytesSkipped == 0L) { 
         int b = read(); 
         if (b < 0) { 
          break; // we reached EOF 
         } else { 
          bytesSkipped = 1; // we read one byte 
         } 
        } 
        totalBytesSkipped += bytesSkipped; 
       } 
       return totalBytesSkipped; 
      } 
     } 

     /** 
     * The actual AsyncTask that will asynchronously download the image. 
     */ 
     class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> { 
      private String url; 
      private final WeakReference<ImageView> imageViewReference; 

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

      /** 
      * Actual download method. 
      */ 
      @Override 
      protected Bitmap doInBackground(String... params) { 
       url = params[0]; 
       return downloadBitmap(url); 
      } 

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

       addBitmapToCache(url, bitmap); 

       if (imageViewReference != null) { 
        ImageView imageView = imageViewReference.get(); 
        BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView); 
        // Change bitmap only if this process is still associated with it 
        // Or if we don't use any bitmap to task association (NO_DOWNLOADED_DRAWABLE mode) 
        if ((this == bitmapDownloaderTask) || (mode != Mode.CORRECT)) { 
         imageView.setImageBitmap(bitmap); 
        } 
       } 
      } 
     } 


     /** 
     * A fake Drawable that will be attached to the imageView while the download is in progress. 
     * 
     * <p>Contains a reference to the actual download task, so that a download task can be stopped 
     * if a new binding is required, and makes sure that only the last started download process can 
     * bind its result, independently of the download finish order.</p> 
     */ 
     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(); 
      } 
     } 

     public void setMode(Mode mode) { 
      this.mode = mode; 
      clearCache(); 
     } 


     /* 
     * Cache-related fields and methods. 
     * 
     * We use a hard and a soft cache. A soft reference cache is too aggressively cleared by the 
     * Garbage Collector. 
     */ 

     private static final int HARD_CACHE_CAPACITY = 10; 
     private static final int DELAY_BEFORE_PURGE = 10 * 1000; // in milliseconds 

     // Hard cache, with a fixed maximum capacity and a life duration 
     private final HashMap<String, Bitmap> sHardBitmapCache = 
      new LinkedHashMap<String, Bitmap>(HARD_CACHE_CAPACITY/2, 0.75f, true) { 
      @Override 
      protected boolean removeEldestEntry(LinkedHashMap.Entry<String, Bitmap> eldest) { 
       if (size() > HARD_CACHE_CAPACITY) { 
        // Entries push-out of hard reference cache are transferred to soft reference cache 
        sSoftBitmapCache.put(eldest.getKey(), new SoftReference<Bitmap>(eldest.getValue())); 
        return true; 
       } else 
        return false; 
      } 
     }; 

     // Soft cache for bitmaps kicked out of hard cache 
     private final static ConcurrentHashMap<String, SoftReference<Bitmap>> sSoftBitmapCache = 
      new ConcurrentHashMap<String, SoftReference<Bitmap>>(HARD_CACHE_CAPACITY/2); 

     private final Handler purgeHandler = new Handler(); 

     private final Runnable purger = new Runnable() { 
      public void run() { 
       clearCache(); 
      } 
     }; 

     /** 
     * Adds this bitmap to the cache. 
     * @param bitmap The newly downloaded bitmap. 
     */ 
     private void addBitmapToCache(String url, Bitmap bitmap) { 
      if (bitmap != null) { 
       synchronized (sHardBitmapCache) { 
        sHardBitmapCache.put(url, bitmap); 
       } 
      } 
     } 

     /** 
     * @param url The URL of the image that will be retrieved from the cache. 
     * @return The cached bitmap or null if it was not found. 
     */ 
     private Bitmap getBitmapFromCache(String url) { 
      // First try the hard reference cache 
      synchronized (sHardBitmapCache) { 
       final Bitmap bitmap = sHardBitmapCache.get(url); 
       if (bitmap != null) { 
        // Bitmap found in hard cache 
        // Move element to first position, so that it is removed last 
        sHardBitmapCache.remove(url); 
        sHardBitmapCache.put(url, bitmap); 
        return bitmap; 
       } 
      } 

      // Then try the soft reference cache 
      SoftReference<Bitmap> bitmapReference = sSoftBitmapCache.get(url); 
      if (bitmapReference != null) { 
       final Bitmap bitmap = bitmapReference.get(); 
       if (bitmap != null) { 
        // Bitmap found in soft cache 
        return bitmap; 
       } else { 
        // Soft reference has been Garbage Collected 
        sSoftBitmapCache.remove(url); 
       } 
      } 

      return null; 
     } 

     /** 
     * Clears the image cache used internally to improve performance. Note that for memory 
     * efficiency reasons, the cache will automatically be cleared after a certain inactivity delay. 
     */ 
     public void clearCache() { 
      sHardBitmapCache.clear(); 
      sSoftBitmapCache.clear(); 
     } 

     /** 
     * Allow a new delay before the automatic cache clear is done. 
     */ 
     private void resetPurgeTimer() { 
      purgeHandler.removeCallbacks(purger); 
      purgeHandler.postDelayed(purger, DELAY_BEFORE_PURGE); 
     } 
    } 
0

당신은 최고

  • 빌더 패턴
  • 죄에 Vinci 안드로이드 도서관에게 그것의 testet 및 지원 Concurrency와 그 빌드를 사용할 수 있습니다 gleton 패턴
  • 콜백 패턴

및 핸들은 그녀 자신과 사용하기 쉬운하여 다중 이미지를 다운로드. 당신은 모든 다운로드 요청의 결과 얻을 싶다면

:

Vinci 
    .base(context) 
    .process() 
    .load(uri, 
     new Request() { 
        @Override 
        public void onSuccess(Bitmap bitmap) { 
         viewHolder.Writer.setImageBitmap(bitmap); 
         //or 
         //do some thing with bitmap 
        } 

        @Override 
        public void onFailure(Throwable e) { 
         Log.e(e.getClass().getSimpleName(), e.getMessage()); 
        } 
      }); 

ImageView에 당신 싶어 쇼 이미지가 사용 거기에이

Vinci 
    .base(context) 
    .process() 
    .load(uri) 
    .view(imageView); 

처럼 사용할 수 있는지 RecycleView이 부분을 참조하십시오. wiki page

0

피카소 라이브러리를 사용하여 이미지를 ImageViews에로드하기 만하면됩니다. 매우 사용하기 쉽고 동시성도 매우 쉽게 지원됩니다. 예 :

Picasso.with(this.context).load(url_of_image).into(imageView); 
관련 문제