2012-10-30 64 views
0

我正在開發一個android應用程序。我一直在使用延遲加載concept.It正常工作,直到最後幾天,但今天它給予錯誤如何在延遲加載期間設置位圖大小

Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget 

我有,我用bitmap概念

package com.example.shareslab; 

public final class UrlImageViewHelper { 
    private static final String LOGTAG = "UrlImageViewHelper"; 
    public static int copyStream(InputStream input, OutputStream output) throws IOException 
    { 
     byte[] stuff = new byte[1024]; 
     int read = 0; 
     int total = 0; 
     while ((read = input.read(stuff)) != -1) 
     { 
      output.write(stuff, 0, read); 
      total += read; 
     } 
     return total; 
    } 

    static Resources mResources; 
    static DisplayMetrics mMetrics; 
    private static void prepareResources(Context context) { 
     if (mMetrics != null) 
      return; 
     mMetrics = new DisplayMetrics(); 
     Activity act = (Activity)context; 
     act.getWindowManager().getDefaultDisplay().getMetrics(mMetrics); 
     AssetManager mgr = context.getAssets(); 
     mResources = new Resources(mgr, mMetrics, context.getResources().getConfiguration()); 
    } 

    private static BitmapDrawable loadDrawableFromStream(Context context, InputStream stream) { 
     prepareResources(context); 
     final Bitmap bitmap = BitmapFactory.decodeStream(stream); 
     //Log.i(LOGTAG, String.format("Loaded bitmap (%dx%d).", bitmap.getWidth(), bitmap.getHeight())); 
     return new BitmapDrawable(mResources, bitmap); 
    } 

    public static final int CACHE_DURATION_INFINITE = Integer.MAX_VALUE; 
    public static final int CACHE_DURATION_ONE_DAY = 1000 * 60 * 60 * 24; 
    public static final int CACHE_DURATION_TWO_DAYS = CACHE_DURATION_ONE_DAY * 2; 
    public static final int CACHE_DURATION_THREE_DAYS = CACHE_DURATION_ONE_DAY * 3; 
    public static final int CACHE_DURATION_FOUR_DAYS = CACHE_DURATION_ONE_DAY * 4; 
    public static final int CACHE_DURATION_FIVE_DAYS = CACHE_DURATION_ONE_DAY * 5; 
    public static final int CACHE_DURATION_SIX_DAYS = CACHE_DURATION_ONE_DAY * 6; 
    public static final int CACHE_DURATION_ONE_WEEK = CACHE_DURATION_ONE_DAY * 7; 

    public static void setUrlDrawable(final ImageView imageView, final String url, int defaultResource) { 
     setUrlDrawable(imageView.getContext(), imageView, url, defaultResource, CACHE_DURATION_THREE_DAYS); 
    } 

    public static void setUrlDrawable(final ImageView imageView, final String url) { 
     setUrlDrawable(imageView.getContext(), imageView, url, null, CACHE_DURATION_THREE_DAYS); 
    } 

    public static void loadUrlDrawable(final Context context, final String url) { 
     setUrlDrawable(context, null, url, null, CACHE_DURATION_THREE_DAYS); 
    } 

    public static void setUrlDrawable(final ImageView imageView, final String url, Drawable defaultDrawable) { 
     setUrlDrawable(imageView.getContext(), imageView, url, defaultDrawable, CACHE_DURATION_ONE_DAY); 
    } 

    public static void setUrlDrawable(final ImageView imageView, final String url, int defaultResource, long cacheDurationMs) { 
     setUrlDrawable(imageView.getContext(), imageView, url, defaultResource, cacheDurationMs); 
    } 

    public static void loadUrlDrawable(final Context context, final String url, long cacheDurationMs) { 
     setUrlDrawable(context, null, url, null, cacheDurationMs); 
    } 

    public static void setUrlDrawable(final ImageView imageView, final String url, Drawable defaultDrawable, long cacheDurationMs) { 
     setUrlDrawable(imageView.getContext(), imageView, url, defaultDrawable, cacheDurationMs); 
    } 

    private static void setUrlDrawable(final Context context, final ImageView imageView, final String url, int defaultResource, long cacheDurationMs) { 
     Drawable d = null; 
     if (defaultResource != 0) 
      d = imageView.getResources().getDrawable(defaultResource); 
     setUrlDrawable(context, imageView, url, d, cacheDurationMs); 
    } 

    private static boolean isNullOrEmpty(CharSequence s) { 
     return (s == null || s.equals("") || s.equals("null") || s.equals("NULL")); 
    } 

    private static boolean mHasCleaned = false; 

    public static String getFilenameForUrl(String url) { 
     return "" + url.hashCode() + ".urlimage"; 
    } 

    private static void cleanup(Context context) { 
     if (mHasCleaned) 
      return; 
     mHasCleaned = true; 
     try { 
      // purge any *.urlimage files over a week old 
      String[] files = context.getFilesDir().list(); 
      if (files == null) 
       return; 
      for (String file : files) { 
       if (!file.endsWith(".urlimage")) 
        continue; 

       File f = new File(context.getFilesDir().getAbsolutePath() + '/' + file); 
       if (System.currentTimeMillis() > f.lastModified() + CACHE_DURATION_ONE_WEEK) 
        f.delete(); 
      } 
     } 
     catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    private static void setUrlDrawable(final Context context, final ImageView imageView, final String url, final Drawable defaultDrawable, long cacheDurationMs) { 
     cleanup(context); 
     // disassociate this ImageView from any pending downloads 
     if (imageView != null) 
      mPendingViews.remove(imageView); 

     if (isNullOrEmpty(url)) { 
      if (imageView != null) 
       imageView.setImageDrawable(defaultDrawable); 
      return; 
     } 

     final UrlImageCache cache = UrlImageCache.getInstance(); 
     Drawable d = cache.get(url); 
     if (d != null) { 
      //Log.i(LOGTAG, "Cache hit on: " + url); 
      if (imageView != null) 
       imageView.setImageDrawable(d); 
      return; 
     } 

     final String filename = getFilenameForUrl(url); 

     File file = context.getFileStreamPath(filename); 
     if (file.exists()) { 
      try { 
       if (cacheDurationMs == CACHE_DURATION_INFINITE || System.currentTimeMillis() < file.lastModified() + cacheDurationMs) { 
        //Log.i(LOGTAG, "File Cache hit on: " + url + ". " + (System.currentTimeMillis() - file.lastModified()) + "ms old."); 
        FileInputStream fis = context.openFileInput(filename); 
        BitmapDrawable drawable = loadDrawableFromStream(context, fis); 
        fis.close(); 
        if (imageView != null) 
         imageView.setImageDrawable(drawable); 
        cache.put(url, drawable); 
        return; 
       } 
       else { 
        //Log.i(LOGTAG, "File cache has expired. Refreshing."); 
       } 
      } 
      catch (Exception ex) { 
      } 
     } 

     // null it while it is downloading 
     if (imageView != null) 
      imageView.setImageDrawable(defaultDrawable); 

     // since listviews reuse their views, we need to 
     // take note of which url this view is waiting for. 
     // This may change rapidly as the list scrolls or is filtered, etc. 
     //Log.i(LOGTAG, "Waiting for " + url); 
     if (imageView != null) 
      mPendingViews.put(imageView, url); 

     ArrayList<ImageView> currentDownload = mPendingDownloads.get(url); 
     if (currentDownload != null) { 
      // Also, multiple vies may be waiting for this url. 
      // So, let's maintain a list of these views. 
      // When the url is downloaded, it sets the imagedrawable for 
      // every view in the list. It needs to also validate that 
      // the imageview is still waiting for this url. 
      if (imageView != null) 
       currentDownload.add(imageView); 
      return; 
     } 

     final ArrayList<ImageView> downloads = new ArrayList<ImageView>(); 
     if (imageView != null) 
      downloads.add(imageView); 
     mPendingDownloads.put(url, downloads); 

     AsyncTask<Void, Void, Drawable> downloader = new AsyncTask<Void, Void, Drawable>() { 
      @Override 
      protected Drawable doInBackground(Void... params) { 
       AndroidHttpClient client = AndroidHttpClient.newInstance(context.getPackageName()); 
       try { 
        HttpGet get = new HttpGet(url); 
        final HttpParams httpParams = new BasicHttpParams(); 
        HttpClientParams.setRedirecting(httpParams, true); 
        get.setParams(httpParams); 
        HttpResponse resp = client.execute(get); 
        int status = resp.getStatusLine().getStatusCode(); 
        if(status != HttpURLConnection.HTTP_OK){ 
//      Log.i(LOGTAG, "Couldn't download image from Server: " + url + " Reason: " + resp.getStatusLine().getReasonPhrase() + "/" + status); 
         return null; 
        } 
        HttpEntity entity = resp.getEntity(); 
//     Log.i(LOGTAG, url + " Image Content Length: " + entity.getContentLength()); 
        InputStream is = entity.getContent(); 
        FileOutputStream fos = context.openFileOutput(filename, Context.MODE_PRIVATE); 
        copyStream(is, fos); 
        fos.close(); 
        is.close(); 
        FileInputStream fis = context.openFileInput(filename); 
        return loadDrawableFromStream(context, fis); 
       } 
       catch (Exception ex) { 
//     Log.e(LOGTAG, "Exception during Image download of " + url, ex); 
        return null; 
       } 
       finally { 
        client.close(); 
       } 
      } 

      @Override 
      protected void onPostExecute(Drawable result) { 
       if (result == null) 
        result = defaultDrawable; 
       mPendingDownloads.remove(url); 
       cache.put(url, result); 
       for (ImageView iv: downloads) { 
        // validate the url it is waiting for 
        String pendingUrl = mPendingViews.get(iv); 
        if (!url.equals(pendingUrl)) { 
         //Log.i(LOGTAG, "Ignoring out of date request to update view for " + url); 
         continue; 
        } 
        mPendingViews.remove(iv); 
        if (result != null) { 
         final Drawable newImage = result;      
         Drawable newSize=resize(newImage);            
         final ImageView imageView = iv;      
         imageView.setImageDrawable(newSize); 
        } 
       } 
      } 
      private BitmapDrawable resize(Drawable newImage) { 
       // TODO Auto-generated method stub 

       Bitmap d = ((BitmapDrawable)newImage).getBitmap(); 
       Bitmap bitmapOrig = Bitmap.createScaledBitmap(d, 75, 75, false); 
       return new BitmapDrawable(bitmapOrig);            
      } 
     }; 
     downloader.execute(); 
    } 

    private static Hashtable<ImageView, String> mPendingViews = new Hashtable<ImageView, String>(); 
    private static Hashtable<String, ArrayList<ImageView>> mPendingDownloads = new Hashtable<String, ArrayList<ImageView>>(); 
} 

一類無論是在我的應用程序解析的文字和圖片我的應用中的另一個問題是,當我從詳細信息頁面返回時,圖像尺寸變得非常小。我該如何處理?

+1

請指定要在哪行,你有OutOfMemory錯誤....在最後的位圖位= BitmapFactory.decodeStream(流) –

+1

@SanketKachhela; – user1773279

回答

0

嘗試使用BitmapFactory選項作爲

BitmapFactory.Options op=new BitmapFactory.Options(); 
op.inSampleSize=4; 
final Bitmap bitmap = BitmapFactory.decodeStream(stream,null,op); 
+0

@maninder ... thanku – user1773279

+0

你可以改變inSampleSize爲2,4,8 ......也就是2的倍數....但它會降低質量 –

+0

什麼可以做停止降低質量 – user1773279