我正在使用延迟加载类Imageloader从Web服务器获取图像,我在同一个活动中有大约3个Listviews,由于某种原因,其中一个listviews以错误的方式绑定图像。我想加载我的活动然后启动加载每个列表视图的图像。这有什么有效的方法吗? Lazyload曾经工作过......我怎么能指出每个视图应该加载到每个图像?任何帮助,将不胜感激 :)
public class ImageLoader {
private HashMap<String, Bitmap> cache=new HashMap<String, Bitmap>();
private RotateAnimation rotate=null;
private String MainDirectory=".Beirut.com";
private String Directory=".images";
private File cacheDir;
public ImageLoader(Context context){
//Make the background thread low priority. This way it will not affect the UI performance
photoLoaderThread.setPriority(Thread.NORM_PRIORITY-1);
//checking if the main Directory exist?
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),MainDirectory);
else
cacheDir=context.getCacheDir();
if(!cacheDir.exists())
cacheDir.mkdirs();
//Find the dir to save cached images
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),MainDirectory+"/"+Directory);
else
cacheDir=context.getCacheDir();
if(!cacheDir.exists())
cacheDir.mkdirs();
}
final int stub_id=R.drawable.refresh_resized_silver;
public void DisplayImage(String url, Activity activity, ImageView imageView)
{
//Log.e("Image to load",url);
rotate=new RotateAnimation(0f, 360f,
Animation.RELATIVE_TO_SELF,0.5f,
Animation.RELATIVE_TO_SELF,0.5f);
rotate.setDuration(1000L);
rotate.setRepeatMode(Animation.INFINITE);
rotate.setRepeatCount(Animation.INFINITE);
imageView.setImageResource(stub_id);
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
//imageView.setBackgroundResource(stub_id);
imageView.startAnimation(rotate);
if(cache.containsKey(url)){
imageView.setImageBitmap(cache.get(url));
imageView.invalidate();
imageView.setScaleType(ScaleType.CENTER_INSIDE);
imageView.clearAnimation();
//Log.e("Animation","Cleared");
}
else
{
queuePhoto(url, activity, imageView);
}
}
private void queuePhoto(String url, Activity activity, ImageView imageView)
{
//This ImageView may be used for other images before. So there may be some old tasks in the queue. We need to discard them.
photosQueue.Clean(imageView);
PhotoToLoad p=new PhotoToLoad(url, imageView);
synchronized(photosQueue.photosToLoad){
photosQueue.photosToLoad.push(p);
photosQueue.photosToLoad.notifyAll();
}
//start thread if it's not started yet
if(photoLoaderThread.getState()==Thread.State.NEW)
photoLoaderThread.start();
}
public static Bitmap loadImageFromUrl(String url) {
InputStream inputStream;
Bitmap b;
try {
if(url.contains(" ")){
url=url.replace(" ", "%20");
}
//Log.e("Error link",url);
inputStream = (InputStream) new URL(url).getContent();
BitmapFactory.Options bpo= new BitmapFactory.Options();
bpo.inJustDecodeBounds = true;
bpo.inJustDecodeBounds = false;
if(bpo.outWidth>400){
bpo.inSampleSize = 1;
b=BitmapFactory.decodeStream(inputStream, null,bpo );
}else{
bpo.inSampleSize=1;
b=BitmapFactory.decodeStream(inputStream, null,bpo );
}
return b;
}catch (IOException e) {
throw new RuntimeException(e);
}
}
private Bitmap getBitmap(String url)
{
//I identify images by hashcode. Not a perfect solution, good for the demo.
String filename=String.valueOf(url.hashCode());
File f=new File(cacheDir, filename);
//from SD cache
Bitmap b = decodeFile(f);
if(b!=null){
return b;
}
//from web
try {
Bitmap bitmap=null;
InputStream is=new URL(url).openStream();
OutputStream os = new FileOutputStream(f);
Utils.CopyStream(is, os);
os.close();
bitmap = decodeFile(f);
//bitmap=loadImageFromUrl(url);
return bitmap;
} catch (Exception ex){
ex.printStackTrace();
return null;
}
}
//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
try {
//decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE=300;
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 inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
try{
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
}catch(FileNotFoundException e){
return null;
}
} catch (FileNotFoundException e) {}
return null;
}
//Task for the queue
private class PhotoToLoad
{
public String url;
public ImageView imageView;
public PhotoToLoad(String u, ImageView i){
url=u;
imageView=i;
}
}
PhotosQueue photosQueue=new PhotosQueue();
public void stopThread()
{
photoLoaderThread.interrupt();
}
//stores list of photos to download
class PhotosQueue
{
private Stack<PhotoToLoad> photosToLoad=new Stack<PhotoToLoad>();
//removes all instances of this ImageView
public void Clean(ImageView image)
{
for(int j=0 ;j<photosToLoad.size();){
if(photosToLoad.get(j).imageView==image){
photosToLoad.remove(j);
}else{
++j;
}
}
}
}
class PhotosLoader extends Thread {
public void run() {
try {
while(true)
{
//thread waits until there are any images to load in the queue
if(photosQueue.photosToLoad.size()==0)
synchronized(photosQueue.photosToLoad){
photosQueue.photosToLoad.wait();
}
if(photosQueue.photosToLoad.size()!=0)
{
PhotoToLoad photoToLoad;
synchronized(photosQueue.photosToLoad){
photoToLoad=photosQueue.photosToLoad.pop();
}
Bitmap bmp=getBitmap(photoToLoad.url);
cache.put(photoToLoad.url, bmp);
Object tag=photoToLoad.imageView.getTag();
if(tag!=null && ((String)tag).equals(photoToLoad.url)){
BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad.imageView);
Activity a=(Activity)photoToLoad.imageView.getContext();
a.runOnUiThread(bd);
}
}
if(Thread.interrupted())
break;
}
} catch (InterruptedException e) {
}
}
}
PhotosLoader photoLoaderThread=new PhotosLoader();
class BitmapDisplayer implements Runnable
{
Bitmap bitmap;
ImageView imageView;
public BitmapDisplayer(Bitmap b, ImageView i){bitmap=b;imageView=i;}
public void run()
{
if(bitmap!=null)
imageView.setImageBitmap(bitmap);
else
imageView.setImageResource(stub_id);
BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
drawable.setAntiAlias(true);
imageView.setScaleType(ScaleType.CENTER_INSIDE);
imageView.clearAnimation();
//Log.e("Animation","Cleared");
}
}
public void clearCache() {
cache.clear();
//clear SD cache
File[] files=cacheDir.listFiles();
for(File f:files)
f.delete();
}
}
public class ImageLoader {
private HashMap<String, Bitmap> cache=new HashMap<String, Bitmap>();
private RotateAnimation rotate=null;
private String MainDirectory=".Beirut.com";
private String Directory=".images";
private File cacheDir;
public ImageLoader(Context context){
//Make the background thread low priority. This way it will not affect the UI performance
photoLoaderThread.setPriority(Thread.NORM_PRIORITY-1);
//checking if the main Directory exist?
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),MainDirectory);
else
cacheDir=context.getCacheDir();
if(!cacheDir.exists())
cacheDir.mkdirs();
//Find the dir to save cached images
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),MainDirectory+"/"+Directory);
else
cacheDir=context.getCacheDir();
if(!cacheDir.exists())
cacheDir.mkdirs();
}
final int stub_id=R.drawable.refresh_resized_silver;
public void DisplayImage(String url, Activity activity, ImageView imageView)
{
//Log.e("Image to load",url);
rotate=new RotateAnimation(0f, 360f,
Animation.RELATIVE_TO_SELF,0.5f,
Animation.RELATIVE_TO_SELF,0.5f);
rotate.setDuration(1000L);
rotate.setRepeatMode(Animation.INFINITE);
rotate.setRepeatCount(Animation.INFINITE);
imageView.setImageResource(stub_id);
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
//imageView.setBackgroundResource(stub_id);
imageView.startAnimation(rotate);
if(cache.containsKey(url)){
imageView.setImageBitmap(cache.get(url));
imageView.invalidate();
imageView.setScaleType(ScaleType.CENTER_INSIDE);
imageView.clearAnimation();
//Log.e("Animation","Cleared");
}
else
{
queuePhoto(url, activity, imageView);
}
}
private void queuePhoto(String url, Activity activity, ImageView imageView)
{
//This ImageView may be used for other images before. So there may be some old tasks in the queue. We need to discard them.
photosQueue.Clean(imageView);
PhotoToLoad p=new PhotoToLoad(url, imageView);
synchronized(photosQueue.photosToLoad){
photosQueue.photosToLoad.push(p);
photosQueue.photosToLoad.notifyAll();
}
//start thread if it's not started yet
if(photoLoaderThread.getState()==Thread.State.NEW)
photoLoaderThread.start();
}
public static Bitmap loadImageFromUrl(String url) {
InputStream inputStream;
Bitmap b;
try {
if(url.contains(" ")){
url=url.replace(" ", "%20");
}
//Log.e("Error link",url);
inputStream = (InputStream) new URL(url).getContent();
BitmapFactory.Options bpo= new BitmapFactory.Options();
bpo.inJustDecodeBounds = true;
bpo.inJustDecodeBounds = false;
if(bpo.outWidth>400){
bpo.inSampleSize = 1;
b=BitmapFactory.decodeStream(inputStream, null,bpo );
}else{
bpo.inSampleSize=1;
b=BitmapFactory.decodeStream(inputStream, null,bpo );
}
return b;
}catch (IOException e) {
throw new RuntimeException(e);
}
}
private Bitmap getBitmap(String url)
{
//I identify images by hashcode. Not a perfect solution, good for the demo.
String filename=String.valueOf(url.hashCode());
File f=new File(cacheDir, filename);
//from SD cache
Bitmap b = decodeFile(f);
if(b!=null){
return b;
}
//from web
try {
Bitmap bitmap=null;
InputStream is=new URL(url).openStream();
OutputStream os = new FileOutputStream(f);
Utils.CopyStream(is, os);
os.close();
bitmap = decodeFile(f);
//bitmap=loadImageFromUrl(url);
return bitmap;
} catch (Exception ex){
ex.printStackTrace();
return null;
}
}
//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
try {
//decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE=300;
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 inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
try{
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
}catch(FileNotFoundException e){
return null;
}
} catch (FileNotFoundException e) {}
return null;
}
//Task for the queue
private class PhotoToLoad
{
public String url;
public ImageView imageView;
public PhotoToLoad(String u, ImageView i){
url=u;
imageView=i;
}
}
PhotosQueue photosQueue=new PhotosQueue();
public void stopThread()
{
photoLoaderThread.interrupt();
}
//stores list of photos to download
class PhotosQueue
{
private Stack<PhotoToLoad> photosToLoad=new Stack<PhotoToLoad>();
//removes all instances of this ImageView
public void Clean(ImageView image)
{
for(int j=0 ;j<photosToLoad.size();){
if(photosToLoad.get(j).imageView==image){
photosToLoad.remove(j);
}else{
++j;
}
}
}
}
class PhotosLoader extends Thread {
public void run() {
try {
while(true)
{
//thread waits until there are any images to load in the queue
if(photosQueue.photosToLoad.size()==0)
synchronized(photosQueue.photosToLoad){
photosQueue.photosToLoad.wait();
}
if(photosQueue.photosToLoad.size()!=0)
{
PhotoToLoad photoToLoad;
synchronized(photosQueue.photosToLoad){
photoToLoad=photosQueue.photosToLoad.pop();
}
Bitmap bmp=getBitmap(photoToLoad.url);
cache.put(photoToLoad.url, bmp);
Object tag=photoToLoad.imageView.getTag();
if(tag!=null && ((String)tag).equals(photoToLoad.url)){
BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad.imageView);
Activity a=(Activity)photoToLoad.imageView.getContext();
a.runOnUiThread(bd);
}
}
if(Thread.interrupted())
break;
}
} catch (InterruptedException e) {
}
}
}
PhotosLoader photoLoaderThread=new PhotosLoader();
class BitmapDisplayer implements Runnable
{
Bitmap bitmap;
ImageView imageView;
public BitmapDisplayer(Bitmap b, ImageView i){bitmap=b;imageView=i;}
public void run()
{
if(bitmap!=null)
imageView.setImageBitmap(bitmap);
else
imageView.setImageResource(stub_id);
BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
drawable.setAntiAlias(true);
imageView.setScaleType(ScaleType.CENTER_INSIDE);
imageView.clearAnimation();
//Log.e("Animation","Cleared");
}
}
public void clearCache() {
cache.clear();
//clear SD cache
File[] files=cacheDir.listFiles();
for(File f:files)
f.delete();
}
}
和getview方法如下:
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
ViewHolder holder;
if(convertView==null){
vi = inflater.inflate(R.layout.videoitem, null);
holder=new ViewHolder();
holder.text=(TextView)vi.findViewById(R.id.text);
holder.image=(ImageView)vi.findViewById(R.id.image);
holder.typetext=(TextView)vi.findViewById(R.id.typetext);
holder.description=(TextView)vi.findViewById(R.id.description);
vi.setTag(holder);
}else{
holder=(ViewHolder)vi.getTag();
}
String dprow="";
//data comes from search list
if(!data.get(position).getTitle().trim().equalsIgnoreCase("")){
dprow+="<b><strike>"+data.get(position).getTitle().trim()+"</strike></b>"+"<br>";
}
String urltoload="http://img.youtube.com/vi/"+data.get(position).getYoutube()+"/0.jpg";
if(urltoload.contains(" ")){
urltoload=urltoload.replace(" ", "%20");
}
holder.text.setText(Html.fromHtml(dprow));
holder.image.setTag(urltoload);
holder.typetext.setText(data.get(position).getType());
holder.description.setText(urltoload);
imageLoader.DisplayImage(urltoload, activity, holder.image);
return vi;
}
我使用notifyDataSetChanged()来刷新视图但它的速度很慢。是否有更好的方法可以在背景中为每个视图加载图像!
答案 0 :(得分:0)
使用3个不同的图像加载器(延迟加载器的对象)来加载每个类的图像。因为懒惰列表检查旧请求和视图(如果存在)然后取消它并添加新图像的请求。