Android非同期ロード画像詳細の方法一(2)
18920 ワード
FileCache.JAvaは以下の通りです.
MemoryCache.JAvaは以下の通りです.
ImageLoader.JAvaは以下の通りです.
package cn.loadImages;
import java.io.File;
import android.content.Context;
import android.net.Uri;
import android.os.Environment;
public class FileCache {
private File fileCacheDir;
public FileCache(Context context){
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
fileCacheDir=new File(Environment.getExternalStorageDirectory(),"idealLV001");
}
else{
//context.getCacheDir();
//
fileCacheDir=context.getCacheDir();
}
if(!fileCacheDir.exists()){
fileCacheDir.mkdirs();
}
}
public File getImageFile(String url){
//String filename=String.valueOf(url.hashCode());
//String filename = URLEncoder.encode(url);
Uri uri=Uri.parse(url);
String fileName=uri.getLastPathSegment();
File file= new File(fileCacheDir, fileName);
return file;
}
public void clear() {
File[] files = fileCacheDir.listFiles();
if (files == null) {
return;
}
for (File file : files) {
file.delete();
}
}
}
MemoryCache.JAvaは以下の通りです.
package cn.loadImages;
import java.lang.ref.SoftReference;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import android.graphics.Bitmap;
import android.util.Log;
public class MemoryCache {
private static final String TAG = "xx";
public static HashMap<String, Integer> bitmapsSizeHashMap;
//1
// : Collections.synchronizedMap map
private Map<String, Bitmap> hardBitmapCacheHashMap=
Collections.synchronizedMap(new LinkedHashMap<String, Bitmap>(10,1.5f,true));
//2
private final static ConcurrentHashMap<String, SoftReference<Bitmap>>
softBitmapCacheHashMap = new ConcurrentHashMap<String, SoftReference<Bitmap>>(20);
//
private long allocatedMemoryMaxSize=0;
//
private long nowTotalUsedMemorySize=0;
public MemoryCache(){
//use 10% of available heap size
setAllocatedMemoryMaxSize(Runtime.getRuntime().maxMemory()/10);//85
bitmapsSizeHashMap=new HashMap<String, Integer>();
}
public void setAllocatedMemoryMaxSize(long allocatedMemoryMaxSize){
this.allocatedMemoryMaxSize=allocatedMemoryMaxSize;
Log.i(TAG, "allocatedMemoryMaxSize="+allocatedMemoryMaxSize/1024/1024+"MB");
}
public Bitmap getBitmapFromMemory(String url) {
try {
//1
Bitmap bitmap = hardBitmapCacheHashMap.get(url);
if (bitmap != null) {
// ,
// .
// hardBitmapCacheHashMap
// hardBitmapCacheHashMap
hardBitmapCacheHashMap.remove(url);
hardBitmapCacheHashMap.put(url, bitmap);
return bitmap;
}
//2
// : sHardBitmapCache ,
// sHardBitmapCache , softBitmapCacheHashMap
// softBitmapCacheHashMap
System.out.println("88 get SoftReference ");
System.out.println("88 get SoftReference url="+url);
SoftReference<Bitmap> bitmapReference = softBitmapCacheHashMap.get(url);
if (bitmapReference != null) {
Bitmap bp = bitmapReference.get();
if (bp != null) {
return bp;
} else {
// SoftReference GC
softBitmapCacheHashMap.remove(url);
}
}
return null;
} catch (NullPointerException ex) {
ex.printStackTrace();
return null;
}
}
public void putBitmapToMemory(String url, Bitmap bitmap){
try{
if(!hardBitmapCacheHashMap.containsKey(url)){
nowTotalUsedMemorySize+=getBitmapSizeInBytes(bitmap,url);
System.out.println("88 put nowTotalUsedMemorySize="+nowTotalUsedMemorySize);
checkMemorySizeStatus();
hardBitmapCacheHashMap.put(url, bitmap);
}
}catch(Throwable th){
th.printStackTrace();
}
}
//
// , softBitmapCacheHashMap
// hardBitmapCacheHashMap
private void checkMemorySizeStatus() {
int hardBitmapCacheHashMapSize=hardBitmapCacheHashMap.size();
int count=0;
System.out.println("88 checkSizeStatus nowTotalUsedMemorySize="+nowTotalUsedMemorySize);
System.out.println("88 checkSizeStatus memoryMaxSize="+allocatedMemoryMaxSize);
if(nowTotalUsedMemorySize>=allocatedMemoryMaxSize){
System.out.println("88 checkSizeStatus nowTotalUsedMemorySize>=memoryMaxSize");
System.out.println("88 checkSizeStatus hardBitmapCacheHashMap.size()="+hardBitmapCacheHashMap.size());
Iterator<Entry<String, Bitmap>> iter=hardBitmapCacheHashMap.entrySet().iterator();
//least recently accessed item will be the first one iterated
while(iter.hasNext()){
count++;
Entry<String, Bitmap> entry=iter.next();
if (count==hardBitmapCacheHashMapSize) {
System.out.println("88 checkSizeStatus count="+count);
System.out.println("88 checkSizeStatus memoryMaxSize="+allocatedMemoryMaxSize);
System.out.println("88 checkSizeStatus nowTotalUsedMemorySize="+nowTotalUsedMemorySize);
nowTotalUsedMemorySize-=getBitmapSizeInBytes(entry.getValue(),entry.getKey());
//1 softBitmapCacheHashMap
softBitmapCacheHashMap.put(entry.getKey(),new SoftReference<Bitmap>(entry.getValue()));
System.out.println("88 checkSizeStatus SoftReference url="+entry.getKey());
System.out.println("88 checkSizeStatus SoftReference softBitmapCacheHashMap.size()="+softBitmapCacheHashMap.size());
//2
iter.remove();
//3 bitmapsSizeHashMap
bitmapsSizeHashMap.remove(entry.getKey());
System.out.println("88 checkSizeStatus hardBitmapCacheHashMap.size()="+hardBitmapCacheHashMap.size());
System.out.println("88 checkSizeStatus softBitmapCacheHashMap.size()="+softBitmapCacheHashMap.size());
System.out.println("88 checkSizeStatus nowTotalUsedMemorySize="+nowTotalUsedMemorySize);
System.out.println("88 checkSizeStatus memoryMaxSize="+allocatedMemoryMaxSize);
}
}
}
if(nowTotalUsedMemorySize>=allocatedMemoryMaxSize){
checkMemorySizeStatus();
}
}
public void clear() {
try{
hardBitmapCacheHashMap.clear();
softBitmapCacheHashMap.clear();
bitmapsSizeHashMap.clear();
nowTotalUsedMemorySize=0;
}catch(NullPointerException ex){
ex.printStackTrace();
}
}
// Bitmap
long getBitmapSizeInBytes(Bitmap bitmap,String url) {
if(bitmap==null){
return 0;
}
int bitmapSize=bitmapsSizeHashMap.get(url);
return bitmapSize;
//return bitmap.getRowBytes() * bitmap.getHeight();
}
}
ImageLoader.JAvaは以下の通りです.
package cn.loadImages;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
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.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.ImageView;
import cn.ideallistview.R;
public class ImageLoader {
MemoryCache memoryCache=new MemoryCache();
FileCache fileCache;
private boolean isgetBitmapThumbnail=false;
private final int REQUIRED_BITMAP_WIDTH=50;
private final int REQUIRED_BITMAP_HEIGHT=50;
private final int REQUIRED_BITMAP_MAXNUMOFPIXELS=200*200;
// :
//WeakHashMap , .
// Collections.synchronizedMap WeakHashMap
private Map<ImageView, String> imageViewsWeakHashMap=
Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
ExecutorService executorService;
//
final int defaultImageId=R.drawable.stub;
public ImageLoader(Context context){
fileCache=new FileCache(context);
// ,
executorService=Executors.newFixedThreadPool(5);
}
//
public void displayImage(String url, ImageView imageView){
//1 imageView url imageViewsWeakHashMap
imageViewsWeakHashMap.put(imageView, url);
//2
Bitmap bitmap=memoryCache.getBitmapFromMemory(url);
if(bitmap!=null){
imageView.setImageBitmap(bitmap);
}
//3 , SD
else{
taskQueueForImages(url, imageView);
imageView.setImageResource(defaultImageId);
}
}
private void taskQueueForImages(String url, ImageView imageView){
WillLoadedImageBean willLoadedImageBean=new WillLoadedImageBean(url, imageView);
// Runnable , Future
executorService.submit(new LoaderImagesRunnable(willLoadedImageBean));
}
//
class LoaderImagesRunnable implements Runnable {
WillLoadedImageBean willLoadedImageBean;
LoaderImagesRunnable(WillLoadedImageBean willLoadedImageBean){
this.willLoadedImageBean=willLoadedImageBean;
}
@Override
public void run() {
try{
if(isImageViewReused(willLoadedImageBean)){
return;
}
// Url Bitmap
//1 SDCard
//2 SDCard , , SDCard
//3 SDCard
Bitmap bitmap=getBitmapByUrl(willLoadedImageBean.url);
//4 memoryCache
memoryCache.putBitmapToMemory(willLoadedImageBean.url, bitmap);
if(isImageViewReused(willLoadedImageBean)){
return;
}
//5 Bitmap UI
BitmapDisplayerRunnableInUIThread bitmapDisplayerRunnable
=new BitmapDisplayerRunnableInUIThread(bitmap, willLoadedImageBean);
Activity activity=(Activity)willLoadedImageBean.imageView.getContext();
activity.runOnUiThread(bitmapDisplayerRunnable);
}catch(Throwable th){
th.printStackTrace();
}
}
}
// Url Bitmap
private Bitmap getBitmapByUrl(String url)
{
//1 SD
File file=fileCache.getImageFile(url);
Bitmap bitmap = getBitmapFromSDCardFile(file);
if(bitmap!=null){
return bitmap;
}else{
//2 SD , SD File
bitmap=getBitmapFromNetWork(url,file);
if (bitmap!=null) {
return bitmap;
}
}
return null;
}
private Bitmap getBitmapFromSDCardFile(File file) {
if (!isgetBitmapThumbnail) {
try {
FileInputStream inputStream = new FileInputStream(file);
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
inputStream.close();
return bitmap;
} catch (Exception e) {
e.printStackTrace();
}
} else {
try {
String filePath=file.getAbsolutePath();
int minSideLength=Math.min(REQUIRED_BITMAP_HEIGHT, REQUIRED_BITMAP_WIDTH);
Bitmap bp=Utils.getBitmapThumbnail(filePath, minSideLength, REQUIRED_BITMAP_MAXNUMOFPIXELS);
return bp;
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
// private Bitmap getBitmapFromSDCardFile(File file){
// try {
// //decode image size
// BitmapFactory.Options options1 = new BitmapFactory.Options();
// options1.inJustDecodeBounds = true;
// FileInputStream stream1=new FileInputStream(file);
// BitmapFactory.decodeStream(stream1,null,options1);
// stream1.close();
//
// //Find the correct scale value. It should be the power of 2.
// final int REQUIRED_SIZE=70;
// int width_tmp=options1.outWidth, height_tmp=options1.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 inSampleSize
// BitmapFactory.Options options2 = new BitmapFactory.Options();
// options2.inSampleSize=scale;
// FileInputStream stream2=new FileInputStream(file);
// Bitmap bitmap=BitmapFactory.decodeStream(stream2, null, options2);
// stream2.close();
//
// System.out.println("xxxxxxxxxxxxxxxxx f.getPath="+file.getPath());
// System.out.println("xxxxxxxxxxxxxxxxx options1.outWidth="+options1.outWidth);
// System.out.println("xxxxxxxxxxxxxxxxx options1.outHeight="+options1.outHeight);
// System.out.println("xxxxxxxxxxxxxxxxx scale="+scale);
// return bitmap;
// } catch (FileNotFoundException e) {
// }
// catch (IOException e) {
// e.printStackTrace();
// }
// return null;
// }
// SDCard
private Bitmap getBitmapFromNetWork(String url,File file){
try {
Bitmap bitmap=null;
URL imageUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
conn.setConnectTimeout(30000);
conn.setReadTimeout(30000);
conn.setInstanceFollowRedirects(true);
InputStream is=conn.getInputStream();
//
MemoryCache.bitmapsSizeHashMap.put(url,conn.getContentLength());
OutputStream os = new FileOutputStream(file);
Utils.copyStream(is, os);
os.close();
bitmap = getBitmapFromSDCardFile(file);
return bitmap;
} catch (Throwable ex){
ex.printStackTrace();
if(ex instanceof OutOfMemoryError){
memoryCache.clear();
}
return null;
}
}
// UI Bitmap
class BitmapDisplayerRunnableInUIThread implements Runnable{
Bitmap bitmap;
WillLoadedImageBean willLoadedImageBean;
public BitmapDisplayerRunnableInUIThread(Bitmap bitmap, WillLoadedImageBean willLoadedImageBean){
this.bitmap=bitmap;
this.willLoadedImageBean=willLoadedImageBean;
}
public void run(){
if(isImageViewReused(willLoadedImageBean)){
return;
}
if(bitmap!=null){
willLoadedImageBean.imageView.setImageBitmap(bitmap);
}
else{
willLoadedImageBean.imageView.setImageResource(defaultImageId);
}
}
}
//Task for the queue
private class WillLoadedImageBean
{
public String url;
public ImageView imageView;
public WillLoadedImageBean(String url, ImageView imageView){
this.url=url;
this.imageView=imageView;
}
}
boolean isImageViewReused(WillLoadedImageBean willLoadedImageBean){
String imageUrl=imageViewsWeakHashMap.get(willLoadedImageBean.imageView);
if(imageUrl==null || !imageUrl.equals(willLoadedImageBean.url)){
return true;
}
return false;
}
public void clearCache() {
memoryCache.clear();
fileCache.clear();
}
}