Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Please remove file operation and heavy bitmap operation from getView().</p> <p>Instead of using this use following class for handling image in your list view. </p> <pre><code>public class ImageStorage { private String mBaseDir; private static final String TAG = "Image Storage"; private static boolean DEBUG = false; public static final int DEFAULT_CACHE_SIZE = 64; private BasicBitmapCache mCache; private Handler mHandler = new Handler(); private ExecutorService mExecutor = Executors.newCachedThreadPool(); private Set&lt;LoadRequest&gt; mActiveRequests = new HashSet&lt;LoadRequest&gt;(); public static class LoadRequest { public LoadRequest(String key, ImageView v) { if (key == null) throw new NullPointerException("key must not be null"); mKey = key; mImageView = v; } public ImageView getImageView() { return mImageView; } public String getKey() { return mKey; } @Override public boolean equals(Object b) { if (b instanceof LoadRequest) return mKey.equals(((LoadRequest) b).getKey()); return false; } private String mKey; private ImageView mImageView; } public ImageStorage(String baseDir) { this.mBaseDir = baseDir; this.mCache = new BasicBitmapCache(DEFAULT_CACHE_SIZE); } public boolean exists(String key) { File file = new File(new File(mBaseDir), key); return file.exists(); } public Bitmap loadData(String key) { if (!exists(key)) { return null; } // load the bitmap as-is (no scaling, no crop) Bitmap bitmap = null; File file = new File(new File(mBaseDir), key); FileInputStream fis = null; try { fis = new FileInputStream(file); bitmap = BitmapFactory.decodeStream(fis); if (bitmap == null) { // something wrong with the persistent data, can't be decoded to // bitmap. // removeDir(file); // Let's remove this file will gets // downloaded again from server throw new RuntimeException( "data from db can't be decoded to bitmap"); } return bitmap; } catch (IOException e) { if (DEBUG) Log.e(TAG, "error loading bitmap", e); return null; } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { } } } } public void storeData(String key, Bitmap data) { if (data == null || data.isRecycled()) return; //Scaling image before storing data = scaleBitmap(data); OutputStream outputStream = null; try { File file = new File(new File(mBaseDir), key); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } outputStream = new FileOutputStream(file); if (!data.compress(Bitmap.CompressFormat.PNG, 100, outputStream)) { throw new RuntimeException("failed to compress bitmap"); } } catch (IOException e) { if (DEBUG) Log.e(TAG, "error storing bitmap", e); } finally { if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { } } } } public void clear() { try { this.removeDir(new File(mBaseDir)); } catch (IOException e) { throw new RuntimeException(e); } } public int deleteFile(String key) { if (!exists(key)) { return -1; } File file = new File(new File(mBaseDir), key); boolean deleted = file.delete(); if (!deleted) return 0; return 1; } /** * Delete a directory * * @param d * the directory to delete * */ private void removeDir(File d) throws IOException { // to see if this directory is actually a symbolic link to a directory, // we want to get its canonical path - that is, we follow the link to // the file it's actually linked to File candir = d.getCanonicalFile(); // a symbolic link has a different canonical path than its actual path, // unless it's a link to itself if (!candir.equals(d.getAbsoluteFile())) { // this file is a symbolic link, and there's no reason for us to // follow it, because then we might be deleting something outside of // the directory we were told to delete return; } // now we go through all of the files and subdirectories in the // directory and delete them one by one File[] files = candir.listFiles(); if (files != null) { for (int i = 0; i &lt; files.length; i++) { File file = files[i]; // in case this directory is actually a symbolic link, or it's // empty, we want to try to delete the link before we try // anything boolean deleted = file.delete(); if (!deleted) { // deleting the file failed, so maybe it's a non-empty // directory if (file.isDirectory()) removeDir(file); // otherwise, there's nothing else we can do } } } // now that we tried to clear the directory out, we can try to delete it // again d.delete(); } public Bitmap loadImage(LoadRequest r) { if (r == null || r.getKey() == null) { // throw new IllegalArgumentException( "null or empty request"); return null; } ImageView v = r.getImageView(); if (v != null) { synchronized (v) { v.setTag(r.getKey()); // bind URI to the ImageView, to prevent // image write-back of earlier requests. } } mExecutor.submit(newRequestCall(r)); return null; } private Bitmap scaleBitmap(Bitmap image) { int width = image.getWidth(); int height = image.getHeight(); float scale = (float)480/(float)width; Matrix matrix = new Matrix(); matrix.postScale(scale, scale); Bitmap scaledBitmap = Bitmap.createScaledBitmap(image, (int) (width * scale), (int) (height * scale), true); // Bitmap scaledBitmap = Bitmap.createBitmap(images.get(i), 0, 0, width, // height, matrix, true); return scaledBitmap; } private Callable&lt;LoadRequest&gt; newRequestCall(final LoadRequest request) { return new Callable&lt;LoadRequest&gt;() { public LoadRequest call() { synchronized (mActiveRequests) { while (mActiveRequests.contains(request)) { try { mActiveRequests.wait(); } catch (InterruptedException e) { } } mActiveRequests.add(request); } Bitmap data = null; try { String key = request.getKey(); data = mCache.loadData(key); if (data == null) { if (DEBUG) Log.d(TAG, "cache missing " + request.getKey()); // then check the persistent storage data = loadData(key); if (data != null) { if (DEBUG) Log.d(TAG, "found in persistent: " + request.getKey()); mCache.storeData(key, data); } } if (data != null &amp;&amp; !data.isRecycled() &amp;&amp; request.getImageView() != null) { final Bitmap theData = data; final ImageView iv = request.getImageView(); synchronized (iv) { if (iv != null &amp;&amp; iv.getTag() == request.getKey()) { mHandler.post(new Runnable() { @Override public void run() { if (iv.getTag() == request.getKey() &amp;&amp; !theData.isRecycled()) { iv.setAnimation(null); iv.setImageBitmap(theData); } } }); } } } } catch (Throwable e) { if (DEBUG) Log.e(TAG, "error handling request " + request.getKey(), e); } finally { synchronized (mActiveRequests) { mActiveRequests.remove(request); mActiveRequests.notifyAll(); // wake up pending requests // who's querying the // same URL. } if (DEBUG) Log.d(TAG, "finished request for: " + request.getKey()); } return request; } }; } } </code></pre> <p>and in your adapter get image using</p> <pre><code>getImageStorage().loadImage( new LoadRequest(//name of image, //your image view)); </code></pre> <p>and Basic Bitmap Cache is here...</p> <pre><code>/** * Basic implementation of BitmapCache * * @author Chirag Jain */ public class BasicBitmapCache { private static class CacheEntry { public Bitmap data; public int nUsed; public long timestamp; } private static final String TAG = "BasicBitmapCache"; private static final boolean DEBUG = false; private int mMaxSize; private HashMap&lt;String, CacheEntry&gt; mMap = new HashMap&lt;String, CacheEntry&gt;(); /** * max number of resource this cache contains * * @param size */ public BasicBitmapCache(int size) { this.mMaxSize = size; } public synchronized boolean exists(String key) { return mMap.get(key) != null; } public synchronized void invalidate(String key) { CacheEntry e = mMap.get(key); Bitmap data = e.data; data.recycle(); mMap.remove(key); if (DEBUG) Log.d(TAG, key + " is invalidated from the cache"); } public synchronized void clear() { for (String key : mMap.keySet()) { invalidate(key); } } /** * If the cache storage is full, return an item to be removed. * * Default strategy: the least and oldest out: O(n) * * @return item key */ protected synchronized String findItemToInvalidate() { Map.Entry&lt;String, CacheEntry&gt; out = null; for (Map.Entry&lt;String, CacheEntry&gt; e : mMap.entrySet()) { if (out == null || e.getValue().nUsed &lt; out.getValue().nUsed || e.getValue().nUsed == out.getValue().nUsed &amp;&amp; e.getValue().timestamp &lt; out.getValue().timestamp) { out = e; } } return out.getKey(); } public synchronized Bitmap loadData(String key) { if (!exists(key)) { return null; } CacheEntry res = mMap.get(key); res.nUsed++; res.timestamp = System.currentTimeMillis(); return res.data; } public synchronized void storeData(String key, Bitmap data) { if (this.exists(key) || data == null || data.isRecycled()) { return; } CacheEntry res = new CacheEntry(); res.nUsed = 1; res.timestamp = System.currentTimeMillis(); res.data = data; // if the number exceeds, move an item out // to prevent the storage from increasing indefinitely. if (mMap.size() &gt;= mMaxSize) { String outkey = this.findItemToInvalidate(); this.invalidate(outkey); } mMap.put(key, res); } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload