During development with a huge amount of images, most of all image loaders available out there, does not display(caches) the images smoothlty. For this reason, i have tryed to put all the code "pieces" i found in the internet together to get a almost perfect image loader for my application. The result is shown bellow. It works very well for me. It may be also interesting for other developers. Here is my solution:
The Loader interface
/** * Drawable loader used to create and cache thumbnails while presenting it in a gallery preview. * IMPORTANT: instantiate it in your main activity like this: ** @author Ricardo Ferreira * @version 1.0 * @since 03/04/2014 */ public interface Loader { /** * Clears all instance data and stops running threads */ public void Reset() ; /** * Loads a drawable into an image. Call this method inside of getView(...) from your concrete * implementation of BaseAdapter. ** protected void onCreate(final Bundle savedInstanceState) { * super.onCreate(savedInstanceState); * ... * DrawableLoader.getInstance(this); * ... * } *
** public View getView(int position, View convertView, ViewGroup parent){ * ... * String url = PATH_FILE + pathImage;// path to your storage like "/storage/..." * ImageView imageView = (ImageView)holder.imgView; * final Drawable placeholder = mContext.getResources().getDrawable(R.drawable.placeholder); * DrawableLoader.getInstance(mContext).loadDrawable(url, imageView, placeholder); * ... * } ** @param url file path to the storage location * @param imageView the image to be presented in a list view or grid view * @param placeholder the place holder image to be shown, while the loading is running. */ public void loadDrawable(final String url, final ImageView imageView, Drawable placeholder); }
The Loader implementation
/** * Drawable loader used to create and cache thumbnails while presenting it in a gallery preview. * IMPORTANT: instantiate it in your main activity like this: ** @author Ricardo Ferreira * @version 1.0 * @since 03/04/2014 */ @SuppressLint("HandlerLeak") public class DrawableLoader implements Loader{ private final Map < String, SoftReference < Drawable > > mCache = new HashMap < String, SoftReference < Drawable > >(); private final LinkedList < Drawable > mChacheController = new LinkedList < Drawable > (); private ExecutorService mThreadPool; private final Map < ImageView, String > mImageViews = Collections.synchronizedMap(new WeakHashMap < ImageView, String >()); public final static int MAX_CACHE_SIZE = 1024; public final int THREAD_POOL_SIZE = 5; private Context mContext; private static Loader loader; // SINGLETON private DrawableLoader(Context context) { mThreadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE); mContext=context; } public static Loader getInstance(Context ctx){ if(loader==null){ loader = new DrawableLoader(ctx); } return loader; } public void Reset() { ExecutorService oldThreadPool = mThreadPool; mThreadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE); oldThreadPool.shutdownNow(); mChacheController.clear(); mCache.clear(); mImageViews.clear(); } public void loadDrawable(final String url, final ImageView imageView, Drawable placeholder) { mImageViews.put(imageView, url); Drawable drawable = getDrawableFromCache(url); if (drawable != null) { imageView.setImageDrawable(drawable); } else { imageView.setImageDrawable(placeholder); queueJob(url, imageView, placeholder); } } private Drawable getDrawableFromCache(String url) { if (mCache.containsKey(url)) { return mCache.get(url).get(); } return null; } private synchronized void putDrawableInCache(String url, Drawable drawable) { int chacheControllerSize = mChacheController.size(); if (chacheControllerSize > MAX_CACHE_SIZE){ mChacheController.subList(0, MAX_CACHE_SIZE / 2).clear(); } mChacheController.addLast(drawable); mCache.put(url, new SoftReference* protected void onCreate(final Bundle savedInstanceState) { * super.onCreate(savedInstanceState); * ... * DrawableLoader.getInstance(this); * ... * } *
*(drawable)); } private void queueJob(final String url, final ImageView imageView, final Drawable placeholder) { /* Create handler in UI thread. */ final Handler handler = new Handler() { @Override public void handleMessage(Message msg) { String tag = mImageViews.get(imageView); if (tag != null && tag.equals(url)) { if (imageView.isShown()) if (msg.obj != null) { imageView.setImageDrawable((Drawable) msg.obj); } else { imageView.setImageDrawable(placeholder); } } } }; mThreadPool.submit(new Runnable() { @Override public void run() { final Drawable bmp = downloadDrawable(url); // if the view is not visible anymore, //the image will be ready for next time in cache if (imageView.isShown()) { Message message = Message.obtain(); message.obj = bmp; handler.sendMessage(message); } } }); } private Drawable downloadDrawable(String url) { final Bitmap decodeBitmap = ViewHelper.decodeBitmap(url.replaceAll("file://", ""), 100); Drawable drawable = new BitmapDrawable(mContext.getResources(), decodeBitmap); putDrawableInCache(url, drawable); return drawable; } /** pass new URL(urlString) to it, while urlString is the path to the drawable like: * http://www.google.com.br/images/your_image.png */ protected Drawable downloadDrawable(URL url) { try { InputStream is = getInputStream(url); Drawable drawable = Drawable.createFromStream(is, url.getPath()); putDrawableInCache(url.getPath(), drawable); return drawable; } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } private InputStream getInputStream(URL url) throws MalformedURLException, IOException { //URL url = new URL(urlString); URLConnection connection; connection = url.openConnection(); connection.setUseCaches(true); connection.connect(); InputStream response = connection.getInputStream(); return response; } }
That's all. Hope you like it! ;)
😱👇 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO 😱👇
Be sure to read, it will change your life!
Show your work by Austin Kleon: https://amzn.to/34NVmwx
This book is a must read - it will put you in another level! (Expert)
Agile Software Development, Principles, Patterns, and Practices: https://amzn.to/30WQSm2
Write cleaner code and stand out!
Clean Code - A Handbook of Agile Software Craftsmanship: https://amzn.to/33RvaSv
This book is very practical, straightforward and to the point! Worth every penny!
Kotlin for Android App Development (Developer's Library): https://amzn.to/33VZ6gp
Needless to say, these are top right?
Apple AirPods Pro: https://amzn.to/2GOICxy
😱👆 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO 😱👆