Android: Help in adapting ListView adapter with an ImageLoader Class (LazyList)

后端 未结 4 682
隐瞒了意图╮
隐瞒了意图╮ 2020-12-15 14:40

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 sav

4条回答
  •  挽巷
    挽巷 (楼主)
    2020-12-15 14:42

    Seems that you did not use any view holder in your adapter

    I have made changes in your classes.Hope it will works for you with out any difficulties

    The ImageThreadLoader class

     import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.URL;
    import java.util.HashMap;
    import java.util.Stack;
    
    import android.app.Activity;
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.widget.ImageView;
    
    public class ImageThreadLoader {
    
        //the simplest in-memory cache implementation. This should be replaced with something like SoftReference or BitmapOptions.inPurgeable(since 1.6)
        /** The cache. */
        private HashMap cache=new HashMap();
    
        /** The cache dir. */
        private File cacheDir;
    
        /**
         * Instantiates a new image loader.
         *
         * @param context the context
         */
        public ImageThreadLoader(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(),"cache_dir_img");
            else
                cacheDir=context.getCacheDir();
            if(!cacheDir.exists())
                cacheDir.mkdirs();
        }
        //This is used for a stub when the user can not see the actual image..
        //this images will be seen
        final int stub_id =R.drawable.sample_image;
    
    
        /**
         * Display image.
         *
         * @param url the url
         * @param activity the activity
         * @param imageView the image view
         */
        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);
            }    
        }
    
        /**
         * Queue photo.
         *
         * @param url the url
         * @param activity the activity
         * @param imageView the image view
         */
        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();
        }
    
        /**
         * Gets the bitmap.
         *
         * @param url the url
         * @return the bitmap
         */
        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);
                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
        /**
         * Decode file.
         *
         * @param f the f
         * @return the bitmap
         */
        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 photosToLoad=new Stack();
    
            //removes all instances of this ImageView
            /**
             * Clean.
             *
             * @param image the image
             */
            public void Clean(ImageView image)
            {
                for(int j=0 ;j

    Now your ProjectAdapter class

    import java.util.List;
    
    import android.app.Activity;
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    public class ProjectAdapter extends ArrayAdapter {
    
        int resource;
        String response;
        Context context;
        List items;
        private ImageThreadLoader imageLoader;
        LayoutInflater mInflater;
        Activity activity;
    
        // Initialize adapter
        public ProjectAdapter(Context context, int resource, List items,
                Activity activity) {
            super(context, resource, items);
            this.resource = resource;
            imageLoader = new ImageThreadLoader(context);
            this.items = items;
            mInflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            this.activity = activity;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
    
            ViewHolder holder = null;
    
            // Inflate the view
            if (convertView == null) {
    
                convertView = mInflater.inflate(resource, null);
                holder = new ViewHolder();
                holder.image = (ImageView) convertView.findViewById(R.id.image);
                holder.textTitle = (TextView) convertView
                        .findViewById(R.id.txt_title);
                convertView.setTag(holder);
    
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
    
            Project project = items.get(position);
    
            holder.textTitle.setText(project.project_title);
    
            String imageurl = project.smallImageUrl;
            holder.image.setTag(imageurl);
            imageLoader.displayImage(imageurl, activity, holder.image);
            return convertView;
    
        }
    
        static class ViewHolder {
    
            TextView textTitle;
    
            ImageView image;
        }
    

    And at last when you set the adapter in your ListView after getting the web data, use this

    your_listview.setAdapter(your_ProjectAdapter_instance );
    your_ProjectAdapter_instance .notifyDataSetChanged();
    

提交回复
热议问题