android listview 滾動時非同步載入圖片的問題
LoadImage.java
Java程式碼
package com.gowin.cach;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;
public class LoadImage {
private ExecutorService executorService; // 固定五個執行緒來
private ImageMemoryCache memoryCache;// 記憶體快取
private ImageFileCache fileCache;// 檔案快取
private Map<String, ImageView> taskMap;// 存放任務
public LoadImage() {
executorService = Executors.newFixedThreadPool(10);
memoryCache = new ImageMemoryCache();
fileCache = new ImageFileCache();
taskMap = new HashMap<String, ImageView>();
}
public void addTask(String url, ImageView img) {
Bitmap bitmap=memoryCache.getBitmapFromCache(url);
if(bitmap!=null)
{
img.setImageBitmap(bitmap);
}else
{
synchronized (taskMap) {
taskMap.put(Integer.toString(img.hashCode()), img);
}
}
}
public void doTask() {
synchronized (taskMap) {
Collection<ImageView> con = taskMap.values();
for (ImageView i : con) {
if (i != null) {
if (i.getTag() != null) {
loadImage((String) i.getTag(), i);
}
}
}
taskMap.clear();
}
}
private void loadImage(String url, ImageView img) {
/*** 加入新的任務***/
executorService.submit(new TaskWithResult(new TaskHandler(url, img),
url));
}
/*** 獲得一個圖片,從三個地方獲取,首先是記憶體快取,然後是檔案快取,最後從網路獲取***/
private Bitmap getBitmap(String url) {
// 從記憶體快取中獲取圖片
Bitmap result;
result = memoryCache.getBitmapFromCache(url);
if (result == null) {
// 檔案快取中獲取
result = fileCache.getImage(url);
if (result == null) {
// 從網路獲取
result = ImageGetForHttp.downloadBitmap(url);
if (result != null) {
memoryCache.addBitmapToCache(url, result);
fileCache.saveBmpToSd(result, url);
}
} else {
// 新增到記憶體快取
memoryCache.addBitmapToCache(url, result);
}
}
return result;
}
/*** 完成訊息***/
private class TaskHandler extends Handler {
String url;
ImageView img;
public TaskHandler(String url, ImageView img) {
this.url = url;
this.img = img;
}
@Override
public void handleMessage(Message msg) {
/*** 檢視imageview需要顯示的圖片是否被改變***/
if (img.getTag().equals(url)) {
if (msg.obj != null) {
Bitmap bitmap = (Bitmap) msg.obj;
img.setImageBitmap(bitmap);
}
}
}
}
/*** 子執行緒任務***/
private class TaskWithResult implements Callable<String> {
private String url;
private Handler handler;
public TaskWithResult(Handler handler, String url) {
this.url = url;
this.handler = handler;
}
@Override
public String call() throws Exception {
Message msg = new Message();
msg.obj = getBitmap(url);
if (msg.obj != null) {
handler.sendMessage(msg);
}
return url;
}
}
}
package com.gowin.cach;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;
public class LoadImage {
private ExecutorService executorService; // 固定五個執行緒來
private ImageMemoryCache memoryCache;// 記憶體快取
private ImageFileCache fileCache;// 檔案快取
private Map<String, ImageView> taskMap;// 存放任務
public LoadImage() {
executorService = Executors.newFixedThreadPool(10);
memoryCache = new ImageMemoryCache();
fileCache = new ImageFileCache();
taskMap = new HashMap<String, ImageView>();
}
public void addTask(String url, ImageView img) {
Bitmap bitmap=memoryCache.getBitmapFromCache(url);
if(bitmap!=null)
{
img.setImageBitmap(bitmap);
}else
{
synchronized (taskMap) {
taskMap.put(Integer.toString(img.hashCode()), img);
}
}
}
public void doTask() {
synchronized (taskMap) {
Collection<ImageView> con = taskMap.values();
for (ImageView i : con) {
if (i != null) {
if (i.getTag() != null) {
loadImage((String) i.getTag(), i);
}
}
}
taskMap.clear();
}
}
private void loadImage(String url, ImageView img) {
/*** 加入新的任務***/
executorService.submit(new TaskWithResult(new TaskHandler(url, img),
url));
}
/*** 獲得一個圖片,從三個地方獲取,首先是記憶體快取,然後是檔案快取,最後從網路獲取***/
private Bitmap getBitmap(String url) {
// 從記憶體快取中獲取圖片
Bitmap result;
result = memoryCache.getBitmapFromCache(url);
if (result == null) {
// 檔案快取中獲取
result = fileCache.getImage(url);
if (result == null) {
// 從網路獲取
result = ImageGetForHttp.downloadBitmap(url);
if (result != null) {
memoryCache.addBitmapToCache(url, result);
fileCache.saveBmpToSd(result, url);
}
} else {
// 新增到記憶體快取
memoryCache.addBitmapToCache(url, result);
}
}
return result;
}
/*** 完成訊息***/
private class TaskHandler extends Handler {
String url;
ImageView img;
public TaskHandler(String url, ImageView img) {
this.url = url;
this.img = img;
}
@Override
public void handleMessage(Message msg) {
/*** 檢視imageview需要顯示的圖片是否被改變***/
if (img.getTag().equals(url)) {
if (msg.obj != null) {
Bitmap bitmap = (Bitmap) msg.obj;
img.setImageBitmap(bitmap);
}
}
}
}
/*** 子執行緒任務***/
private class TaskWithResult implements Callable<String> {
private String url;
private Handler handler;
public TaskWithResult(Handler handler, String url) {
this.url = url;
this.handler = handler;
}
@Override
public String call() throws Exception {
Message msg = new Message();
msg.obj = getBitmap(url);
if (msg.obj != null) {
handler.sendMessage(msg);
}
return url;
}
}
}
ImageMemoryCache.java (http://www.my400800.cn )
Java程式碼
package com.gowin.cach;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.concurrent.ConcurrentHashMap;
import android.graphics.Bitmap;
/****
*記憶體中的快取
****/
public class ImageMemoryCache {
private static final int HARD_CACHE_CAPACITY = 30;
private HashMap<String, Bitmap> mHardBitmapCache ;
private final static ConcurrentHashMap<String, SoftReference<Bitmap>> mSoftBitmapCache =
new ConcurrentHashMap<String, SoftReference<Bitmap>>(HARD_CACHE_CAPACITY / 2);
public ImageMemoryCache()
{
mHardBitmapCache =
new LinkedHashMap<String, Bitmap>(HARD_CACHE_CAPACITY / 2, 0.75f, true) {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
protected boolean removeEldestEntry(LinkedHashMap.Entry<String, Bitmap> eldest) {
if (size() > HARD_CACHE_CAPACITY) {
// Entries push-out of hard reference cache are transferred to soft reference cache
mSoftBitmapCache.put(eldest.getKey(), new SoftReference<Bitmap>(eldest.getValue()));
return true;
} else
return false;
}
};
}
/**
* 從快取中獲取圖片
*/
public Bitmap getBitmapFromCache(String url) {
// 先從mHardBitmapCache快取中獲取
synchronized (mHardBitmapCache) {
final Bitmap bitmap =mHardBitmapCache.get(url);
if (bitmap != null) {
//如果找到的話,把元素移到linkedhashmap的最前面,從而保證在LRU演算法中是最後被刪除
mHardBitmapCache.remove(url);
mHardBitmapCache.put(url,bitmap);
return bitmap;
}
}
//如果mHardBitmapCache中找不到,到mSoftBitmapCache中找
SoftReference<Bitmap>bitmapReference = mSoftBitmapCache.get(url);
if (bitmapReference != null) {
final Bitmap bitmap =bitmapReference.get();
if (bitmap != null) {
//將圖片移回硬快取
mHardBitmapCache.put(url, bitmap);
mSoftBitmapCache.remove(url);
return bitmap;
} else {
mSoftBitmapCache.remove(url);
}
}
return null;
}
/***新增圖片到快取***/
public void addBitmapToCache(String url, Bitmap bitmap) {
if (bitmap != null) {
synchronized (mHardBitmapCache) {
mHardBitmapCache.put(url, bitmap);
}
}
}
}
package com.gowin.cach;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.concurrent.ConcurrentHashMap;
import android.graphics.Bitmap;
/****
*記憶體中的快取
****/
public class ImageMemoryCache {
private static final int HARD_CACHE_CAPACITY = 30;
private HashMap<String, Bitmap> mHardBitmapCache ;
private final static ConcurrentHashMap<String, SoftReference<Bitmap>> mSoftBitmapCache =
new ConcurrentHashMap<String, SoftReference<Bitmap>>(HARD_CACHE_CAPACITY / 2);
public ImageMemoryCache()
{
mHardBitmapCache =
new LinkedHashMap<String, Bitmap>(HARD_CACHE_CAPACITY / 2, 0.75f, true) {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
protected boolean removeEldestEntry(LinkedHashMap.Entry<String, Bitmap> eldest) {
if (size() > HARD_CACHE_CAPACITY) {
// Entries push-out of hard reference cache are transferred to soft reference cache
mSoftBitmapCache.put(eldest.getKey(), new SoftReference<Bitmap>(eldest.getValue()));
return true;
} else
return false;
}
};
}
/**
* 從快取中獲取圖片
*/
public Bitmap getBitmapFromCache(String url) {
// 先從mHardBitmapCache快取中獲取
synchronized (mHardBitmapCache) {
final Bitmap bitmap =mHardBitmapCache.get(url);
if (bitmap != null) {
//如果找到的話,把元素移到linkedhashmap的最前面,從而保證在LRU演算法中是最後被刪除
mHardBitmapCache.remove(url);
mHardBitmapCache.put(url,bitmap);
return bitmap;
}
}
//如果mHardBitmapCache中找不到,到mSoftBitmapCache中找
SoftReference<Bitmap>bitmapReference = mSoftBitmapCache.get(url);
if (bitmapReference != null) {
final Bitmap bitmap =bitmapReference.get();
if (bitmap != null) {
//將圖片移回硬快取
mHardBitmapCache.put(url, bitmap);
mSoftBitmapCache.remove(url);
return bitmap;
} else {
mSoftBitmapCache.remove(url);
}
}
return null;
}
/***新增圖片到快取***/
public void addBitmapToCache(String url, Bitmap bitmap) {
if (bitmap != null) {
synchronized (mHardBitmapCache) {
mHardBitmapCache.put(url, bitmap);
}
}
}
}
ImageFileCache.java
Java程式碼
package com.gowin.cach;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Comparator;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.os.StatFs;
import android.util.Log;
public class ImageFileCache {
private static final String CACHDIR = "data/gowin/imgCach";
private static final String WHOLESALE_CONV = ".cach";
/**過期時間3天**/
private static final long mTimeDiff = 3 * 24 * 60 * 60 * 1000;
public ImageFileCache()
{
//清理檔案快取
removeCache(getDirectory());
}
public Bitmap getImage(final String url) {
final String path = getDirectory() + "/" + convertUrlToFileName(url);
File file = new File(path);
if (file.exists()) {
Bitmap bmp=BitmapFactory.decodeFile(path);
if(bmp==null)
{
file.delete();
}else
{
updateFileTime(path);
return bmp;
}
}
return null;
}
/***快取空間大小****/
private static final int FREE_SD_SPACE_NEEDED_TO_CACHE=10;
public void saveBmpToSd(Bitmap bm, String url) {
if (bm == null) {
//需要儲存的是一個空值
return;
}
//判斷sdcard上的空間
if (FREE_SD_SPACE_NEEDED_TO_CACHE >freeSpaceOnSd()) {
//SD空間不足
return;
}
String filename =convertUrlToFileName(url);
String dir = getDirectory();
File file = new File(dir +"/" + filename);
try {
file.createNewFile();
OutputStream outStream = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
outStream.flush();
outStream.close();
} catch (FileNotFoundException e) {
Log.w("ImageFileCache","FileNotFoundException");
} catch (IOException e) {
Log.w("ImageFileCache","IOException");
}
}
private static final int CACHE_SIZE=10;
// 清理快取
/**
* 計算儲存目錄下的檔案大小,
* 當檔案總大小大於規定的CACHE_SIZE或者sdcard剩餘空間小於FREE_SD_SPACE_NEEDED_TO_CACHE的規定
* 那麼刪除40%最近沒有被使用的檔案
*
* @param dirPath
* @param filename
*/
private boolean removeCache(String dirPath) {
File dir = new File(dirPath);
File[] files = dir.listFiles();
if (files == null) {
return true;
}
if (!android.os.Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED)) {
return false;
}
int dirSize = 0;
for (int i = 0; i < files.length; i++) {
if (files[i].getName().contains(WHOLESALE_CONV)) {
dirSize += files[i].length();
}
}
if (dirSize > CACHE_SIZE * MB
|| FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
int removeFactor = (int) ((0.4 * files.length) + 1);
Arrays.sort(files, new FileLastModifSort());
Log.i("ImageFileCache", "清理快取檔案");
for (int i = 0; i < removeFactor; i++) {
if (files[i].getName().contains(WHOLESALE_CONV)) {
files[i].delete();
}
}
}
if (freeSpaceOnSd() <= CACHE_SIZE) {
return false;
}
return true;
}
/**
* TODO 根據檔案的最後修改時間進行排序*
*/
private class FileLastModifSort implements Comparator<File> {
public int compare(File arg0, File arg1) {
if (arg0.lastModified() > arg1.lastModified()) {
return 1;
} else if (arg0.lastModified() == arg1.lastModified()) {
return 0;
} else {
return -1;
}
}
}
/**
* 刪除過期檔案
*
* @param dirPath
* @param filename
*/
public void removeExpiredCache(String dirPath, String filename) {
File file = new File(dirPath, filename);
if (System.currentTimeMillis() - file.lastModified() > mTimeDiff) {
Log.i("ImageFileCache", "Clear some expiredcache files ");
file.delete();
}
}
/**
* 修改檔案的最後修改時間
* 這裡需要考慮,是否將使用的圖片日期改為當前日期
* @param path
*/
public void updateFileTime(String path) {
File file = new File(path);
long newModifiedTime = System.currentTimeMillis();
file.setLastModified(newModifiedTime);
}
/**
* 計算sdcard上的剩餘空間
* @return
*/
private int MB=1024*1024;
private int freeSpaceOnSd() {
StatFs stat = new StatFs(Environment.getExternalStorageDirectory() .getPath());
double sdFreeMB = ((double)stat.getAvailableBlocks() * (double) stat.getBlockSize()) / MB;
return (int) sdFreeMB;
}
/**將url轉成檔名**/
private String convertUrlToFileName(String url) {
String[] strs = url.split("/");
return strs[strs.length - 1] + WHOLESALE_CONV;
}
/**獲得快取目錄**/
private String getDirectory() {
String dir = getSDPath() + "/" + CACHDIR;
String substr = dir.substring(0, 4);
if (substr.equals("/mnt")) {
dir = dir.replace("/mnt", "");
}
return dir;
}
/**** 取SD卡路徑不帶/ ****/
public String getSDPath() {
File sdDir = null;
boolean sdCardExist = Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED); // 判斷sd卡是否存在
if (sdCardExist) {
sdDir = Environment.getExternalStorageDirectory();// 獲取跟目錄
}
if(sdDir!=null)
{
return sdDir.toString();
}else
{
return "";
}
}
}
package com.gowin.cach;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Comparator;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.os.StatFs;
import android.util.Log;
public class ImageFileCache {
private static final String CACHDIR = "data/gowin/imgCach";
private static final String WHOLESALE_CONV = ".cach";
/**過期時間3天**/
private static final long mTimeDiff = 3 * 24 * 60 * 60 * 1000;
public ImageFileCache()
{
//清理檔案快取
removeCache(getDirectory());
}
public Bitmap getImage(final String url) {
final String path = getDirectory() + "/" + convertUrlToFileName(url);
File file = new File(path);
if (file.exists()) {
Bitmap bmp=BitmapFactory.decodeFile(path);
if(bmp==null)
{
file.delete();
}else
{
updateFileTime(path);
return bmp;
}
}
return null;
}
/***快取空間大小****/
private static final int FREE_SD_SPACE_NEEDED_TO_CACHE=10;
public void saveBmpToSd(Bitmap bm, String url) {
if (bm == null) {
//需要儲存的是一個空值
return;
}
//判斷sdcard上的空間
if (FREE_SD_SPACE_NEEDED_TO_CACHE >freeSpaceOnSd()) {
//SD空間不足
return;
}
String filename =convertUrlToFileName(url);
String dir = getDirectory();
File file = new File(dir +"/" + filename);
try {
file.createNewFile();
OutputStream outStream = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
outStream.flush();
outStream.close();
} catch (FileNotFoundException e) {
Log.w("ImageFileCache","FileNotFoundException");
} catch (IOException e) {
Log.w("ImageFileCache","IOException");
}
}
private static final int CACHE_SIZE=10;
// 清理快取
/**
* 計算儲存目錄下的檔案大小,
* 當檔案總大小大於規定的CACHE_SIZE或者sdcard剩餘空間小於FREE_SD_SPACE_NEEDED_TO_CACHE的規定
* 那麼刪除40%最近沒有被使用的檔案
*
* @param dirPath
* @param filename
*/
private boolean removeCache(String dirPath) {
File dir = new File(dirPath);
File[] files = dir.listFiles();
if (files == null) {
return true;
}
if (!android.os.Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED)) {
return false;
}
int dirSize = 0;
for (int i = 0; i < files.length; i++) {
if (files[i].getName().contains(WHOLESALE_CONV)) {
dirSize += files[i].length();
}
}
if (dirSize > CACHE_SIZE * MB
|| FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
int removeFactor = (int) ((0.4 * files.length) + 1);
Arrays.sort(files, new FileLastModifSort());
Log.i("ImageFileCache", "清理快取檔案");
for (int i = 0; i < removeFactor; i++) {
if (files[i].getName().contains(WHOLESALE_CONV)) {
files[i].delete();
}
}
}
if (freeSpaceOnSd() <= CACHE_SIZE) {
return false;
}
return true;
}
/**
* TODO 根據檔案的最後修改時間進行排序*
*/
private class FileLastModifSort implements Comparator<File> {
public int compare(File arg0, File arg1) {
if (arg0.lastModified() > arg1.lastModified()) {
return 1;
} else if (arg0.lastModified() == arg1.lastModified()) {
return 0;
} else {
return -1;
}
}
}
/**
* 刪除過期檔案
*
* @param dirPath
* @param filename
*/
public void removeExpiredCache(String dirPath, String filename) {
File file = new File(dirPath, filename);
if (System.currentTimeMillis() - file.lastModified() > mTimeDiff) {
Log.i("ImageFileCache", "Clear some expiredcache files ");
file.delete();
}
}
/**
* 修改檔案的最後修改時間
* 這裡需要考慮,是否將使用的圖片日期改為當前日期
* @param path
*/
public void updateFileTime(String path) {
File file = new File(path);
long newModifiedTime = System.currentTimeMillis();
file.setLastModified(newModifiedTime);
}
/**
* 計算sdcard上的剩餘空間
* @return
*/
private int MB=1024*1024;
private int freeSpaceOnSd() {
StatFs stat = new StatFs(Environment.getExternalStorageDirectory() .getPath());
double sdFreeMB = ((double)stat.getAvailableBlocks() * (double) stat.getBlockSize()) / MB;
return (int) sdFreeMB;
}
/**將url轉成檔名**/
private String convertUrlToFileName(String url) {
String[] strs = url.split("/");
return strs[strs.length - 1] + WHOLESALE_CONV;
}
/**獲得快取目錄**/
private String getDirectory() {
String dir = getSDPath() + "/" + CACHDIR;
String substr = dir.substring(0, 4);
if (substr.equals("/mnt")) {
dir = dir.replace("/mnt", "");
}
return dir;
}
/**** 取SD卡路徑不帶/ ****/
public String getSDPath() {
File sdDir = null;
boolean sdCardExist = Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED); // 判斷sd卡是否存在
if (sdCardExist) {
sdDir = Environment.getExternalStorageDirectory();// 獲取跟目錄
}
if(sdDir!=null)
{
return sdDir.toString();
}else
{
return "";
}
}
}
ImageGetForHttp.java
Java程式碼
package com.gowin.cach;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.http.AndroidHttpClient;
import android.util.Log;
public class ImageGetForHttp {
private static final String LOG_TAG="ImageGetForHttp";
public static Bitmap downloadBitmap(String url) {
//final int IO_BUFFER_SIZE = 4 * 1024;
// AndroidHttpClient is not allowed to be used from the main thread
final HttpClient client = AndroidHttpClient.newInstance("Android");
final HttpGet getRequest = new HttpGet(url);
try {
HttpResponse response = client.execute(getRequest);
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w("ImageDownloader", "Error " + statusCode +
" while retrieving bitmap from " + url);
return null;
}
final HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = null;
try {
inputStream = entity.getContent();
// return BitmapFactory.decodeStream(inputStream);
// Bug on slow connections, fixed in future release.
FilterInputStream fit= new FlushedInputStream(inputStream);
return BitmapFactory.decodeStream(fit);
} finally {
if (inputStream != null) {
inputStream.close();
}
entity.consumeContent();
}
}
} catch (IOException e) {
getRequest.abort();
Log.w(LOG_TAG, "I/O error while retrieving bitmap from " + url, e);
} catch (IllegalStateException e) {
getRequest.abort();
Log.w(LOG_TAG, "Incorrect URL: " + url);
} catch (Exception e) {
getRequest.abort();
Log.w(LOG_TAG, "Error while retrieving bitmap from " + url, e);
} finally {
if ((client instanceof AndroidHttpClient)) {
((AndroidHttpClient) client).close();
}
}
return null;
}
/*
* An InputStream that skips the exact number of bytes provided, unless it reaches EOF.
*/
static class FlushedInputStream extends FilterInputStream {
public FlushedInputStream(InputStream inputStream) {
super(inputStream);
}
@Override
public long skip(long n) throws IOException {
long totalBytesSkipped = 0L;
while (totalBytesSkipped < n) {
long bytesSkipped = in.skip(n - totalBytesSkipped);
if (bytesSkipped == 0L) {
int b = read();
if (b < 0) {
break; // we reached EOF
} else {
bytesSkipped = 1; // we read one byte
}
}
totalBytesSkipped += bytesSkipped;
}
return totalBytesSkipped;
}
}
}
package com.gowin.cach;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.http.AndroidHttpClient;
import android.util.Log;
public class ImageGetForHttp {
private static final String LOG_TAG="ImageGetForHttp";
public static Bitmap downloadBitmap(String url) {
//final int IO_BUFFER_SIZE = 4 * 1024;
// AndroidHttpClient is not allowed to be used from the main thread
final HttpClient client = AndroidHttpClient.newInstance("Android");
final HttpGet getRequest = new HttpGet(url);
try {
HttpResponse response = client.execute(getRequest);
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w("ImageDownloader", "Error " + statusCode +
" while retrieving bitmap from " + url);
return null;
}
final HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = null;
try {
inputStream = entity.getContent();
// return BitmapFactory.decodeStream(inputStream);
// Bug on slow connections, fixed in future release.
FilterInputStream fit= new FlushedInputStream(inputStream);
return BitmapFactory.decodeStream(fit);
} finally {
if (inputStream != null) {
inputStream.close();
}
entity.consumeContent();
}
}
} catch (IOException e) {
getRequest.abort();
Log.w(LOG_TAG, "I/O error while retrieving bitmap from " + url, e);
} catch (IllegalStateException e) {
getRequest.abort();
Log.w(LOG_TAG, "Incorrect URL: " + url);
} catch (Exception e) {
getRequest.abort();
Log.w(LOG_TAG, "Error while retrieving bitmap from " + url, e);
} finally {
if ((client instanceof AndroidHttpClient)) {
((AndroidHttpClient) client).close();
}
}
return null;
}
/*
* An InputStream that skips the exact number of bytes provided, unless it reaches EOF.
*/
static class FlushedInputStream extends FilterInputStream {
public FlushedInputStream(InputStream inputStream) {
super(inputStream);
}
@Override
public long skip(long n) throws IOException {
long totalBytesSkipped = 0L;
while (totalBytesSkipped < n) {
long bytesSkipped = in.skip(n - totalBytesSkipped);
if (bytesSkipped == 0L) {
int b = read();
if (b < 0) {
break; // we reached EOF
} else {
bytesSkipped = 1; // we read one byte
}
}
totalBytesSkipped += bytesSkipped;
}
return totalBytesSkipped;
}
}
}
使用時,要救imageview的tag是需要下載的url
在getview時先addtask
當滾動停止的時候呼叫doTask
相關文章
- android ListView非同步載入圖片(雙快取)AndroidView非同步快取
- ListView 之非同步載入圖片亂序View非同步
- ListView效能優化非同步載入圖片View優化非同步
- 載入圖片的問題
- 滾動載入圖片(懶載入)實現原理
- Android實現圖片非同步載入操作Android非同步
- Android9.0使用Glide載入圖片問題AndroidIDE
- Android有效解決載入大圖片時記憶體溢位的問題Android記憶體溢位
- Xamarin.Forms: 無限滾動的ListView(懶載入方式)ORMView
- Android ListView的滾動條樣式AndroidView
- Android之批量載入圖片OOM問題解決方案AndroidOOM
- 一起來實現圖片滾動懶載入
- listView懶載入解決快速拖動卡屏問題View
- Android 圖片載入框架Android框架
- android 載入大量圖片Android
- Android ListView(Selector 背景圖片)AndroidView
- 關於用jquery.masonry.js實現動態載入效果(當頁面滾動條拉到底部時時重新載入圖片)jQueryJS
- Android中ListView滾動時上下邊界的那一抹色彩AndroidView
- Android 載入大圖片,不壓縮圖片Android
- Android實現圖片滾動控制元件Android控制元件
- Android 高效安全載入圖片Android
- 滾動優化(無限滾動載入、滾動元素內有大量dom,造成卡頓問題的優化方案)優化
- 圖片預載入,圖片懶載入,和jsonp中的一個疑問JSON
- android Gallery實現非同步載入網路圖片 並只載入當前停止頁面圖Android非同步
- 小程式記憶體問題–圖片懶載入記憶體
- 一次Web端大量圖片同時載入卡頓問題的優化之旅Web優化
- Glide與CircleImageView載入圓形圖片的問題IDEView
- android短影片開發,圖片視差滾動Android
- (課程學習)Android必學-非同步載入 —— 監聽 ListViewAndroid非同步View
- android glide圖片載入框架AndroidIDE框架
- android之豎直滾動控制元件-ListViewAndroid控制元件View
- mac 下使用自帶apache環境時有圖片載入不出來問題MacApache
- 頁面圖片自動滾動
- FaceBook推出的Android圖片載入庫FrescoAndroid
- C#中PictureBox非同步載入圖片C#非同步
- Glide 一個專注於平滑滾動的圖片載入和快取庫IDE快取
- vue 滾動載入Vue
- 【構建Android快取模組】(三)Controller & 非同步圖片載入Android快取Controller非同步