package com.wilson.android.library;
/*Licensed to the Apache Software Foundation (ASF) under one or morecontributor license agreements. See the NOTICE filedistributed with this work for additional informationregarding copyright ownership. The ASF licenses this fileto you under the Apache License, Version 2.0 (the"License"); you may not use this file except in compliancewith the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,software distributed under the License is distributed on an"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANYKIND, either express or implied. See the License for thespecific language governing permissions and limitationsunder the License.*/import java.io.IOException;
public class DrawableManager {private final Map<String, Drawable> drawableMap;
public DrawableManager() {drawableMap = new HashMap<String, Drawable>();}
public Drawable fetchDrawable(String urlString) {if (drawableMap.containsKey(urlString)) {return drawableMap.get(urlString);}
Log.d(this.getClass().getSimpleName(), "image url:" + urlString);try {InputStream is = fetch(urlString);Drawable drawable = Drawable.createFromStream(is, "src");
if (drawable != null) {drawableMap.put(urlString, drawable);Log.d(this.getClass().getSimpleName(), "got a thumbnail drawable: " + drawable.getBounds() + ", "+ drawable.getIntrinsicHeight() + "," + drawable.getIntrinsicWidth() + ", "+ drawable.getMinimumHeight() + "," + drawable.getMinimumWidth());} else {Log.w(this.getClass().getSimpleName(), "could not get thumbnail");}
return drawable;} catch (MalformedURLException e) {Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);return null;} catch (IOException e) {Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);return null;}}
public void fetchDrawableOnThread(final String urlString, final ImageView imageView) {if (drawableMap.containsKey(urlString)) {imageView.setImageDrawable(drawableMap.get(urlString));}
final Handler handler = new Handler(Looper.getMainLooper()) {@Overridepublic void handleMessage(Message message) {imageView.setImageDrawable((Drawable) message.obj);}};
Thread thread = new Thread() {@Overridepublic void run() {//TODO : set imageView to a "pending" imageDrawable drawable = fetchDrawable(urlString);Message message = handler.obtainMessage(1, drawable);handler.sendMessage(message);}};thread.start();}
private InputStream fetch(String urlString) throws MalformedURLException, IOException {DefaultHttpClient httpClient = new DefaultHttpClient();HttpGet request = new HttpGet(urlString);HttpResponse response = httpClient.execute(request);return response.getEntity().getContent();}}
//Where the first is a string and the other is a imageview to load.
DownloadImageTask.getInstance().loadBitmap(avatarURL, iv_avatar);
以下是缓存的理想代码,然后在检索Web图像时在适配器的getView中调用上述代码:
public class DownloadImageTask {
private LruCache<String, Bitmap> mMemoryCache;
/* Create a singleton class to call this from multiple classes */
private static DownloadImageTask instance = null;
public static DownloadImageTask getInstance() {if (instance == null) {instance = new DownloadImageTask();}return instance;}
//Lock the constructor from public instancesprivate DownloadImageTask() {
// Get max available VM memory, exceeding this amount will throw an// OutOfMemory exception. Stored in kilobytes as LruCache takes an// int in its constructor.final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
// Use 1/8th of the available memory for this memory cache.final int cacheSize = maxMemory / 8;
mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {@Overrideprotected int sizeOf(String key, Bitmap bitmap) {// The cache size will be measured in kilobytes rather than// number of items.return bitmap.getByteCount() / 1024;}};}
public void loadBitmap(String avatarURL, ImageView imageView) {final String imageKey = String.valueOf(avatarURL);
final Bitmap bitmap = getBitmapFromMemCache(imageKey);if (bitmap != null) {imageView.setImageBitmap(bitmap);} else {imageView.setImageResource(R.drawable.ic_launcher);
new DownloadImageTaskViaWeb(imageView).execute(avatarURL);}}
private void addBitmapToMemoryCache(String key, Bitmap bitmap) {if (getBitmapFromMemCache(key) == null) {mMemoryCache.put(key, bitmap);}}
private Bitmap getBitmapFromMemCache(String key) {return mMemoryCache.get(key);}
/* A background process that opens a http stream and decodes a web image. */
class DownloadImageTaskViaWeb extends AsyncTask<String, Void, Bitmap> {ImageView bmImage;
public DownloadImageTaskViaWeb(ImageView bmImage) {this.bmImage = bmImage;}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];Bitmap mIcon = null;try {InputStream in = new java.net.URL(urldisplay).openStream();mIcon = BitmapFactory.decodeStream(in);
}catch (Exception e) {Log.e("Error", e.getMessage());e.printStackTrace();}
addBitmapToMemoryCache(String.valueOf(urldisplay), mIcon);
return mIcon;}
/* After decoding we update the view on the main UI. */protected void onPostExecute(Bitmap result) {bmImage.setImageBitmap(result);}}}
package com.fudiyoxpress.images;
import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.HttpURLConnection;import java.net.URL;import java.util.Collections;import java.util.Map;import java.util.WeakHashMap;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;
import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Handler;import android.widget.ImageView;
import com.fudiyoxpress.R;import com.fudiyoxpress.config.Config;import com.fudiyoxpress.twitter.ScaleBitmap;
public class ImageLoader {
// Initialize MemoryCacheMemoryCache memoryCache = new MemoryCache();
FileCache fileCache;
Context C;
// Create Map (collection) to store image and image url in key value pairprivate Map<ImageView, String> imageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>());ExecutorService executorService;
// handler to display images in UI threadHandler handler = new Handler();
public ImageLoader(Context context) {
C = context;fileCache = new FileCache(context);
// Creates a thread pool that reuses a fixed number of// threads operating off a shared unbounded queue.executorService = Executors.newFixedThreadPool(5);
}
// default image show in list (Before online image download)final int stub_id = R.drawable.restlogoplaceholder;
public void DisplayImage(String url, ImageView imageView, Context context,boolean header_flag) {
Bitmap largeIcon = BitmapFactory.decodeResource(context.getResources(),R.drawable.restlogoplaceholder);header_flag = false;// Store image and url in MapimageViews.put(imageView, url);
// Check image is stored in MemoryCache Map or not (see// MemoryCache.java)Bitmap bitmap = memoryCache.get(url);
if (bitmap != null) {// if image is stored in MemoryCache Map then// Show image in listview rowBitmap b = ScaleBitmap.getScaledBitmap(context, bitmap, header_flag);imageView.setImageBitmap(b);
} else {// queue Photo to download from urlqueuePhoto(url, imageView, header_flag);
// Before downloading image show default imageimageView.setImageBitmap(ScaleBitmap.getScaledBitmap(context,largeIcon, header_flag));
}}
private void queuePhoto(String url, ImageView imageView, boolean header_flag) {// Store image and url in PhotoToLoad objectPhotoToLoad p = new PhotoToLoad(url, imageView, header_flag);
// pass PhotoToLoad object to PhotosLoader runnable class// and submit PhotosLoader runnable to executers to run runnable// Submits a PhotosLoader runnable task for execution
executorService.submit(new PhotosLoader(p));}
// Task for the queueprivate class PhotoToLoad {public String url;public ImageView imageView;public boolean b;
public PhotoToLoad(String u, ImageView i, boolean header_flag) {url = u;imageView = i;b = header_flag;}}
class PhotosLoader implements Runnable {PhotoToLoad photoToLoad;
PhotosLoader(PhotoToLoad photoToLoad) {this.photoToLoad = photoToLoad;}
@Overridepublic void run() {try {// Check if image already downloadedif (imageViewReused(photoToLoad))return;// download image from web urlBitmap bmp = getBitmap(photoToLoad.url);
// set image data in Memory CachememoryCache.put(photoToLoad.url, bmp);
if (imageViewReused(photoToLoad))return;
// Get bitmap to displayBitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad);
// Causes the Runnable bd (BitmapDisplayer) to be added to the// message queue.// The runnable will be run on the thread to which this handler// is attached.// BitmapDisplayer run method will callhandler.post(bd);
} catch (Throwable th) {// th.printStackTrace();}}}
private Bitmap getBitmap(String url) {File f = fileCache.getFile(url);
// from SD cache// CHECK : if trying to decode file which not exist in cache return nullBitmap b = decodeFile(f);if (b != null)return b;
// Download image file from webtry {
// // download the imageBitmap bitmap = null;
URL imageURL = null;try {
imageURL = new URL(Config.WEB_URL + "/ServeBlob?id=" + url);
HttpURLConnection connection = (HttpURLConnection) imageURL.openConnection();connection.setDoInput(true);connection.connect();// if(!(new File(imageURL.toString())).exists())// {// imageURL=new URL("");// }InputStream inputStream = connection.getInputStream();
// Constructs a new FileOutputStream that writes to// file// if file not exist then it will create fileOutputStream os = new FileOutputStream(f);
// See Utils class CopyStream method// It will each pixel from input stream and// write pixels to output stream (file)Utils.CopyStream(inputStream, os);
os.close();
BitmapFactory.Options options = new BitmapFactory.Options();options.inSampleSize = 8;
bitmap = BitmapFactory.decodeStream(inputStream, null, options);
} catch (IOException e) {
// e.printStackTrace();}
// Now file created and going to resize file with defined height// Decodes image and scales it to reduce memory consumptionbitmap = decodeFile(f);
return bitmap;
} catch (Throwable ex) {ex.printStackTrace();if (ex instanceof OutOfMemoryError)memoryCache.clear();return null;}}
// Decodes image and scales it to reduce memory consumptionprivate Bitmap decodeFile(File f) {
try {
// Decode image sizeBitmapFactory.Options o = new BitmapFactory.Options();o.inJustDecodeBounds = true;FileInputStream stream1 = new FileInputStream(f);BitmapFactory.decodeStream(stream1, null, o);stream1.close();
// Find the correct scale value. It should be the power of 2.
// Set width/height of recreated imagefinal int REQUIRED_SIZE = 85;
int width_tmp = o.outWidth, height_tmp = o.outHeight;int scale = 1;while (true) {if (width_tmp / 2 < REQUIRED_SIZE|| height_tmp / 2 < REQUIRED_SIZE)break;width_tmp /= 2;height_tmp /= 2;scale *= 2;}
// decode with current scale valuesBitmapFactory.Options o2 = new BitmapFactory.Options();o2.inSampleSize = scale;FileInputStream stream2 = new FileInputStream(f);Bitmap bitmap = BitmapFactory.decodeStream(stream2, null, o2);stream2.close();return bitmap;
} catch (FileNotFoundException e) {} catch (IOException e) {e.printStackTrace();}return null;}
boolean imageViewReused(PhotoToLoad photoToLoad) {
String tag = imageViews.get(photoToLoad.imageView);// Check url is already exist in imageViews MAPif (tag == null || !tag.equals(photoToLoad.url))return true;return false;}
// Used to display bitmap in the UI threadclass BitmapDisplayer implements Runnable {Bitmap bitmap;PhotoToLoad photoToLoad;
public BitmapDisplayer(Bitmap b, PhotoToLoad p) {bitmap = b;photoToLoad = p;}
public void run() {if (imageViewReused(photoToLoad))return;
// Show bitmap on UIif (bitmap != null) {photoToLoad.imageView.setImageBitmap(ScaleBitmap.getScaledBitmap(C, bitmap, photoToLoad.b));} else {
}// photoToLoad.imageView.setImageResource(stub_id);
}}
public void clearCache() {// Clear cache directory downloaded images and stored data in mapsmemoryCache.clear();fileCache.clear();}
}
package com.fudiyoxpress.images;
import java.util.Collections;import java.util.Iterator;import java.util.LinkedHashMap;import java.util.Map;import java.util.Map.Entry;import android.graphics.Bitmap;import android.util.Log;
public class MemoryCache {
private static final String TAG = "MemoryCache";
//Last argument true for LRU orderingprivate Map<String, Bitmap> cache = Collections.synchronizedMap(new LinkedHashMap<String, Bitmap>(10,1.5f,true));
//current allocated sizeprivate long size=0;
//max memory cache folder used to download images in bytesprivate long limit = 1000000;
public MemoryCache(){
//use 25% of available heap sizesetLimit(Runtime.getRuntime().maxMemory()/4);}
public void setLimit(long new_limit){
limit=new_limit;Log.i(TAG, "MemoryCache will use up to "+limit/1024./1024.+"MB");}
public Bitmap get(String id){try{if(!cache.containsKey(id))return null;//NullPointerException sometimes happen here http://code.google.com/p/osmdroid/issues/detail?id=78return cache.get(id);}catch(NullPointerException ex){ex.printStackTrace();return null;}}
public void put(String id, Bitmap bitmap){try{if(cache.containsKey(id))size-=getSizeInBytes(cache.get(id));cache.put(id, bitmap);size+=getSizeInBytes(bitmap);checkSize();}catch(Throwable th){th.printStackTrace();}}
private void checkSize() {Log.i(TAG, "cache size="+size+" length="+cache.size());if(size>limit){Iterator<Entry<String, Bitmap>> iter=cache.entrySet().iterator();//least recently accessed item will be the first one iteratedwhile(iter.hasNext()){Entry<String, Bitmap> entry=iter.next();size-=getSizeInBytes(entry.getValue());iter.remove();if(size<=limit)break;}Log.i(TAG, "Clean cache. New size "+cache.size());}}
public void clear() {try{//NullPointerException sometimes happen here http://code.google.com/p/osmdroid/issues/detail?id=78cache.clear();size=0;}catch(NullPointerException ex){ex.printStackTrace();}}
long getSizeInBytes(Bitmap bitmap) {if(bitmap==null)return 0;return bitmap.getRowBytes() * bitmap.getHeight();}}
package com.fudiyoxpress.images;
import java.io.InputStream;import java.io.OutputStream;
public class Utils {public static void CopyStream(InputStream is, OutputStream os){final int buffer_size=1024;try{
byte[] bytes=new byte[buffer_size];for(;;){//Read byte from input stream
int count=is.read(bytes, 0, buffer_size);if(count==-1)break;
//Write byte from output streamos.write(bytes, 0, count);}}catch(Exception ex){}}}
<com.facebook.shimmer.ShimmerFrameLayoutandroid:id=“@+id/shimmer_view_container”android:layout_width=“wrap_content”android:layout_height="wrap_content"shimmer:duration="1000">
<here will be your content to display />
</com.facebook.shimmer.ShimmerFrameLayout>