在Android中使用ImageLoader类调整ListView适配器 [英] Adapting ListView adapter with an ImageLoader Class in Android

查看:55
本文介绍了在Android中使用ImageLoader类调整ListView适配器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个实现ImageThreadLoader类的自定义ListView适配器.不幸的是,该类没有启用缓存选项-从网络下载图像并将其保存为缓存.

I have a custom ListView adapter which implements an ImageThreadLoader class. Unfortunately, the class doesn't enable a cache option-download the images from the web and save them as cache.

然后,我发现这个LazyList项目确实非常有用,其行为与ImageThreadLoader类非常相似,但是能够将图像保存为缓存.因此,我想将其ImageLoader类实现为当前的自定义ListView适配器.

And then I found this LazyList project really useful, it behaves quite the same like my ImageThreadLoader class but it's able to save the images as cache. So, I want to implement its ImageLoader class to my current custom ListView adapter.

不幸的是,我的代码和惰性列表的结构完全不同,导致我的尝试有些冲突.例如,LazyList使用字符串数组作为图像URL,另一方面,我使用JSON作为图像URL的源.

Unfortunately the structure of my codes and the Lazylist's is quite different, resulting some conflicts on my attempts. For example, the LazyList use array of strings for the image URL, in the other hand I use JSON as the source of image URL.

这就是为什么我需要帮助来使ListView适配器适应此ImageLoader类的原因.

That's why I need help to adapt my ListView adapter to this ImageLoader class.

以下是代码:

ImageLoader类:

public class ImageLoader {

    //the simplest in-memory cache implementation. This should be replaced with something like SoftReference or BitmapOptions.inPurgeable(since 1.6)
    private HashMap<String, Bitmap> cache=new HashMap<String, Bitmap>();

    private File cacheDir;

    public ImageLoader(Context context){
        //Make the background thead low priority. This way it will not affect the UI performance
        photoLoaderThread.setPriority(Thread.NORM_PRIORITY-1);

        //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(),"Android/data/LazyList");
        else
            cacheDir=context.getCacheDir();
        if(!cacheDir.exists())
            cacheDir.mkdirs();
    }

    final int stub_id=R.drawable.stub;
    public void DisplayImage(String url, Activity activity, ImageView imageView)
    {
        if(cache.containsKey(url))
            imageView.setImageBitmap(cache.get(url));
        else
        {
            queuePhoto(url, activity, imageView);
            imageView.setImageResource(stub_id);
        }    
    }

    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();
    }

    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);
            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=70;
            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;
            return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
        } 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) {
                //allow thread to exit
            }
        }
    }

    PhotosLoader photoLoaderThread=new PhotosLoader();

    //Used to display bitmap in the UI thread
    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);
        }
    }

    public void clearCache() {
        //clear memory cache
        cache.clear();

        //clear SD cache
        File[] files=cacheDir.listFiles();
        for(File f:files)
            f.delete();
    }

}

LazyList项目中的自定义列表视图适配器:

public class LazyAdapter extends BaseAdapter {

    private Activity activity;
    private String[] data;
    private static LayoutInflater inflater=null;
    public ImageLoader imageLoader; 

    public LazyAdapter(Activity a, String[] d) {
        activity = a;
        data=d;
        inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        imageLoader=new ImageLoader(activity.getApplicationContext());
    }

    public int getCount() {
        return data.length;
    }

    public Object getItem(int position) {
        return position;
    }

    public long getItemId(int position) {
        return position;
    }

    public static class ViewHolder{
        public TextView text;
        public ImageView image;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        View vi=convertView;
        ViewHolder holder;
        if(convertView==null){
            vi = inflater.inflate(R.layout.item, null);
            holder=new ViewHolder();
            holder.text=(TextView)vi.findViewById(R.id.text);;
            holder.image=(ImageView)vi.findViewById(R.id.image);
            vi.setTag(holder);
        }
        else
            holder=(ViewHolder)vi.getTag();

        holder.text.setText("item "+position);
        holder.image.setTag(data[position]);
        imageLoader.DisplayImage(data[position], activity, holder.image);
        return vi;
    }
}

这是我的自定义ListView适配器: ProjectAdapter类

public class ProjectAdapter extends ArrayAdapter<Project> {

    int resource;
    String response;
    Context context;
    private final static String TAG = "MediaItemAdapter";

    private ImageThreadLoader imageLoader = new ImageThreadLoader();

    //Initialize adapter
    public ProjectAdapter(Context context, int resource, List<Project> items) {
        super(context, resource, items);
        this.resource=resource;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        TextView textTitle;
        final ImageView image;

        Project pro = getItem(position);

        LinearLayout projectView;
      //Inflate the view
        if(convertView==null)
        {
            projectView = new LinearLayout(getContext());
            String inflater = Context.LAYOUT_INFLATER_SERVICE;
            LayoutInflater vi;
            vi = (LayoutInflater)getContext().getSystemService(inflater);
            vi.inflate(resource, projectView, true);
        }
        else
        {
            projectView = (LinearLayout) convertView;
        }

        try {
          textTitle = (TextView)projectView.findViewById(R.id.txt_title);
          image = (ImageView)projectView.findViewById(R.id.image);
        } catch( ClassCastException e ) {
          Log.e(TAG, "Your layout must provide an image and a text view with ID's icon and text.", e);
          throw e;
        }


        Bitmap cachedImage = null;
        try {
          cachedImage = imageLoader.loadImage(pro.smallImageUrl, new ImageLoadedListener() {
          public void imageLoaded(Bitmap imageBitmap) {
          image.setImageBitmap(imageBitmap);
          notifyDataSetChanged();                }
          });
        } catch (MalformedURLException e) {
          Log.e(TAG, "Bad remote image URL: " + pro.smallImageUrl, e);
        }

        textTitle.setText(pro.project_title);

        if( cachedImage != null ) {
          image.setImageBitmap(cachedImage);
        }

        return projectView;
    }

}

推荐答案

我在此代码加载器代码 ..

检查该代码..

1.在活动"中,获取字符串数组"中的所有图像URL并将其传递..

1.In your Activity get all the images URL in String Array and pass it..

dealAdapter = new LazyAdapter(Activityname.this,VALUE_image);

其中VALUE_image包含您的图像.

where VALUE_image contains your images.

重要的是检查是否在清单文件中添加权限

Important thing is that check whether you add permission in Manifest file

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

创建一个文件,即ImageLoader.class,然后粘贴该链接中提供的Image Loader的代码

Create a file namelyImageLoader.class and paste the code of Image Loader given in that link

然后创建文件Utils.class并将Utils的代码粘贴到该链接中.

Then create file namely Utils.class and paste code of Utils in that link.

在上面的代码中,它检查是否存在Sdcard(如果存在),然后在Sdcard中创建文件夹,并以压缩格式存储所有图像,并在以后检索.

In the above code it checks whether Sdcard is present if so the create folder in Sdcard and store all images in compressed format and retrive it later..

否则,如果没有,它将图像存储在高速缓存中.

Else if no it store images in Cache memory..

第一次从服务器加载图像,然后再次检查是否在Sdcard或高速缓存中,如果是,则检索图像并显示.

First time its load image from the server and next time it check whether it is in Sdcard or in Cache Memory if so retrive the image and Displays..

检查一下.

这篇关于在Android中使用ImageLoader类调整ListView适配器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆