安卓:帮助适应的ListView适配器一个ImageLoader的类 [英] Android: Help in adapting ListView adapter with an ImageLoader Class

查看:72
本文介绍了安卓:帮助适应的ListView适配器一个ImageLoader的类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个实现了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.

不幸的是我的codeS和Lazylist的的结构是完全不同的,由此产生的对我尝试一些冲突。 例如,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 a help here to adapt my ListView adapter to this ImageLoader class.

下面是codeS:

ImageLoader的类,我想实现我的自定义的ListView适配器:

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

}

非常感谢你!

Thank you very much!!

推荐答案

我贴code在此 code对于图像装载机 ..

I posted code in this Code for Image Loader..

检查code ..

1.In您的活动取得字符串数组的所有图像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 并粘贴在该链接给图像装载机的code

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

然后创建一个文件,即 Utils.class 和utils的在该链接粘贴code。

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

在上面的code它会检查SD卡是否为present如果这样的话创建文件夹中的SD卡,并保存在COM pressed格式的所有图像,后来retrive吧..

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..

第一次从服务器下一次它的负载画像检查它是否在SD卡或高速缓存存储器中若有retrive图像和显示器。

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..

瞧瞧吧。

这篇关于安卓:帮助适应的ListView适配器一个ImageLoader的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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