Android:帮助使用ImageLoader类(LazyList)适配ListView适配器



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

然后我发现这个LazyList很有用,它的行为和ImageThreadLoader类很像但它能将图像保存为缓存。我想把它的ImageLoader类实现到我当前的自定义ListView适配器。

不幸的是,我的代码结构和Lazylist的完全不同,导致我的尝试发生了一些冲突。例如,LazyList使用字符串数组作为图像URL,另一方面,我使用JSON作为图像URL的源。

这就是为什么我需要一个帮助来适应我的ListView适配器到这个ImageLoader类。

代码如下:

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类/strong>

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

非常感谢!

编辑

更新:ProjectList活动

    public class ProjectsList extends Activity {
        /** Called when the activity is first created. */
        //ListView that will hold our items references back to main.xml
        ListView lstTest;
        //Array Adapter that will hold our ArrayList and display the items on the ListView
        ProjectAdapter arrayAdapter;
        ProgressDialog dialog;
        //List that will  host our items and allow us to modify that array adapter
        ArrayList<Project> prjcts=null;
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.projects_list);
            //Initialize ListView
            lstTest= (ListView)findViewById(R.id.lstText);
             //Initialize our ArrayList
            prjcts = new ArrayList<Project>();
            //Initialize our array adapter notice how it references the listitems.xml layout
            arrayAdapter = new ProjectAdapter(ProjectsList.this, R.layout.listitems,prjcts,ProjectsList.this);
            //Set the above adapter as the adapter of choice for our list
        lstTest.setAdapter(arrayAdapter);
        if (isOnline())
        {
        //Instantiate the Web Service Class with he URL of the web service not that you must pass
        //WebService webService = new WebService("http://notalentrocks.com/myplaceapp/projects.json");
        WebService webService = new WebService("http://liebenwald.spendino.net/admanager/dev/android/projects.json");
        //Pass the parameters if needed , if not then pass dummy one as follows
        Map<String, String> params = new HashMap<String, String>();
        params.put("var", "");
        //Get JSON response from server the "" are where the method name would normally go if needed example
        // webService.webGet("getMoreAllerts", params);
        String response = webService.webGet("", params);
        try
        {
             dialog = ProgressDialog.show(ProjectsList.this, "", "Fetching Projects...", true);
             dialog.setCancelable(true);
             dialog.setCanceledOnTouchOutside(true);
             dialog.setOnCancelListener(new OnCancelListener() {
                public void onCancel(DialogInterface dialog) {
                }
             });
            //Parse Response into our object
            Type collectionType = new TypeToken<ArrayList<Project>>(){}.getType();
            //JSON expects an list so can't use our ArrayList from the lstart
            List<Project> lst= new Gson().fromJson(response, collectionType);

            //Now that we have that list lets add it to the ArrayList which will hold our items.
            for(Project l : lst)
            {
                prjcts.add(l);
                ConstantData.projectsList.add(l);
            }
            //Since we've modified the arrayList we now need to notify the adapter that
            //its data has changed so that it updates the UI
            arrayAdapter.notifyDataSetChanged();
            dialog.dismiss();
        }
        catch(Exception e)
        {
            Log.d("Error: ", e.getMessage());
        }
        }  
        lstTest.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {              
                Intent care = new Intent(ProjectsList.this, ProjectDetail.class);
                care.putExtra("spendino.de.ProjectDetail.position",position);
                startActivity(care);
            }
        });
    }
    protected boolean isOnline() {
        ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = cm.getActiveNetworkInfo();
        if (netInfo != null && netInfo.isConnected()) {
            return true;
        } else {
             AlertDialog.Builder alertbox = new AlertDialog.Builder(this);
             alertbox.setTitle("spendino Helfomat");
             alertbox.setMessage ("Please check your internet connection");
             alertbox.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                 public void onClick(DialogInterface dialog, int id) {
                      //Main.this.finish();
                 }
             });
             alertbox.show();
            return false;
        }
    }

}

这是我的stacktrace:

05-12 11:36:52.670: ERROR/AndroidRuntime(299): Caused by: java.lang.NullPointerException
05-12 11:36:52.670: ERROR/AndroidRuntime(299):     at android.content.ContextWrapper.getCacheDir(ContextWrapper.java:183)
05-12 11:38:29.386: ERROR/AndroidRuntime(324):     at spendino.de.ImageLoader.<init>(ImageLoader.java:41)
05-12 11:36:52.670: ERROR/AndroidRuntime(299):     at spendino.de.Main.<init>(Main.java:56)

ImageLoader 41 is: cacheDir=context.getCacheDir();主56是:私有ImageLoaderCache imageLoader = new ImageLoaderCache(Main.this);

Main.java

类扩展Activity {/**第一次创建活动时调用。*/

ArrayList<Project> prjcts=null;
private final static String TAG = "MediaItemAdapter";
ImageLoader imageLoader;
private Activity activity;
ImageView image1;
ImageView image2;
ImageView image3;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    if (isOnline())
    {

    prjcts = new ArrayList<Project>();
    WebService webService = new WebService("http://liebenwald.spendino.net/admanager/dev/android/projects.json");
    Map<String, String> params = new HashMap<String, String>();
    params.put("var", "");
    String response = webService.webGet("", params);
    imageLoader = new ImageLoader(Main.this);
    try
    {
        Type collectionType = new TypeToken<ArrayList<Project>>(){}.getType();
        List<Project> lst= new Gson().fromJson(response, collectionType);
        for(Project l : lst)
        {
            prjcts.add(l);
            ConstantData.projectsList.add(l);
        }
    }
    catch(Exception e)
    {
        Log.d("Error: ", e.getMessage());
    }
    try {
        image1 = (ImageView)findViewById(R.id.top1);
        image2 = (ImageView)findViewById(R.id.top2);
        image3 = (ImageView)findViewById(R.id.top3);
      } 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;
      }
      //randomize the index of image entry
      int max = prjcts.size();
      List<Integer> indices = new ArrayList<Integer>(max);
      for(int c = 1; c < max; ++c)
      {
          indices.add(c);
      }
      Random r = new Random();
      int arrIndex = r.nextInt(indices.size());
      int randomIndex1 = indices.get(arrIndex);
      indices.remove(arrIndex);
      int arrIndex2 = r.nextInt(indices.size());
      int randomIndex2 = indices.get(arrIndex2);
      indices.remove(arrIndex2);
      int arrIndex3 = r.nextInt(indices.size());
      int randomIndex3 = indices.get(arrIndex3);
      indices.remove(arrIndex3);

      imageLazy(image1, prjcts.get(randomIndex1));
      imageLazy(image2, prjcts.get(randomIndex2));
      imageLazy(image3, prjcts.get(randomIndex3));
      image1.setOnClickListener(new RandomClickListener(randomIndex1));
      image2.setOnClickListener(new RandomClickListener(randomIndex2));
      image3.setOnClickListener(new RandomClickListener(randomIndex3));
    } 
    final Button project = (Button) findViewById(R.id.btn_projectslist);
    final Button infos = (Button) findViewById(R.id.btn_infos);
    final Button contact = (Button) findViewById(R.id.btn_contact);
    project.setOnClickListener(project_listener);
    infos.setOnClickListener(infos_listener);
    contact.setOnClickListener(contact_listener);
}
/*
 * isOnline - Check if there is a NetworkConnection
 * @return boolean
 */
protected boolean isOnline() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    if (netInfo != null && netInfo.isConnected()) {
        return true;
    } else {
         AlertDialog.Builder alertbox = new AlertDialog.Builder(this);
         alertbox.setTitle("spendino Helfomat");
         alertbox.setMessage ("Bitte überprüfen Sie Ihre Internetverbindung");
         alertbox.setPositiveButton("OK", new DialogInterface.OnClickListener() {
             public void onClick(DialogInterface dialog, int id) {
                  Main.this.finish();
             }
         });
         alertbox.show();
        return false;
    }
}
public static class ViewHolder{
    public ImageView image;
}
public void imageLazy(final ImageView image,Project pro)
{
    imageLoadery.displayImage(pro.smallImageUrl, activity, image);
}
public void setImage(Bitmap cachedImage, final ImageView image, Project pro)
{
    try {
        cachedImage = imageLoader.loadImage(pro.smallImageUrl, new ImageLoadedListener() 
        {
            public void imageLoaded(Bitmap imageBitmap)
            {
                image.setImageBitmap(imageBitmap);              
            }
        });
    } catch (MalformedURLException e) {
        Log.e(TAG, "Bad remote image URL: " + pro.smallImageUrl, e);
    }
    if( cachedImage != null ) {
        image.setImageBitmap(cachedImage);
      }
}
public class RandomClickListener implements View.OnClickListener
{
    private final int randomIndex;
    public RandomClickListener(final int randomIndex)
    {
        this.randomIndex = randomIndex;
    }
    @Override
    public void onClick(View v)
    {
        Intent top = new Intent(Main.this, ProjectDetail.class);
        top.putExtra("spendino.de.ProjectDetail.position", randomIndex);
        startActivity(top);
    }
}
异常堆栈

:

05-12 13:48:12.606: ERROR/AndroidRuntime(433):     at spendino.de.ImageLoaderCache$PhotosLoader.run(ImageLoaderCache.java:244)

似乎您没有在适配器中使用任何视图holder

我对你的课做了改动。希望它对你有用,没有任何困难。

ImageThreadLoader

 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<String, Bitmap> cache=new HashMap<String, Bitmap>();
    /** 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<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
                    break;
                width_tmp/=2;
                height_tmp/=2;
                scale++;
            }
            //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
    /**
     * The Class PhotoToLoad.
     */
    private class PhotoToLoad
    {
        /** The url. */
        public String url;
        /** The image view. */
        public ImageView imageView;
        /**
         * Instantiates a new photo to load.
         *
         * @param u the u
         * @param i the i
         */
        public PhotoToLoad(String u, ImageView i){
            url=u; 
            imageView=i;
        }
    }
    /** The photos queue. */
    PhotosQueue photosQueue=new PhotosQueue();
    /**
     * Stop thread.
     */
    public void stopThread()
    {
        photoLoaderThread.interrupt();
    }
    //stores list of photos to download
    /**
     * The Class PhotosQueue.
     */
    class PhotosQueue
    {
        /** The photos to load. */
        private Stack<PhotoToLoad> photosToLoad=new Stack<PhotoToLoad>();
        //removes all instances of this ImageView
        /**
         * Clean.
         *
         * @param image the image
         */
        public void Clean(ImageView image)
        {
            for(int j=0 ;j<photosToLoad.size();){
                if(photosToLoad.get(j).imageView==image)
                    photosToLoad.remove(j);
                else
                    ++j;
            }
        }
    }
    /**
     * The Class PhotosLoader.
     */
    class PhotosLoader extends Thread {
        /* (non-Javadoc)
         * @see java.lang.Thread#run()
         */
        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);
                        if(((String)photoToLoad.imageView.getTag()).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
            }
        }
    }
    /** The photo loader thread. */
    PhotosLoader photoLoaderThread=new PhotosLoader();
    //Used to display bitmap in the UI thread
    /**
     * The Class BitmapDisplayer.
     */
    class BitmapDisplayer implements Runnable
    {
        /** The bitmap. */
        Bitmap bitmap;
        /** The image view. */
        ImageView imageView;
        /**
         * Instantiates a new bitmap displayer.
         *
         * @param b the b
         * @param i the i
         */
        public BitmapDisplayer(Bitmap b, ImageView i){bitmap=b;imageView=i;}
        /* (non-Javadoc)
         * @see java.lang.Runnable#run()
         */
        public void run()
        {
            if(bitmap!=null)
                imageView.setImageBitmap(bitmap);
            else
              imageView.setImageResource(stub_id);
        }
    }
    /**
     * Clear cache.
     */
    public void clearCache() {
        //clear memory cache
        cache.clear();
        //clear SD cache
        File[] files=cacheDir.listFiles();
        for(File f:files)
            f.delete();
    }
     public static void copyStream(InputStream is, OutputStream os) {
            final int buffer_size=1024;
            try
            {
                byte[] bytes=new byte[buffer_size];
                for(;;)
                {
                  int count=is.read(bytes, 0, buffer_size);
                  if(count==-1)
                      break;
                  os.write(bytes, 0, count);
                }
            }
            catch(Exception ex){}
        }

}
现在你的ProjectAdapter

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<Project> {
    int resource;
    String response;
    Context context;
    List<Project> items;
    private ImageThreadLoader imageLoader;
    LayoutInflater mInflater;
    Activity activity;
    // Initialize adapter
    public ProjectAdapter(Context context, int resource, List<Project> 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;
    }

最后,当您在获得web数据后在ListView中设置适配器时,使用此

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

我确实有不同的数据类型的字符串数组以外的相同的问题,但我使用数组列表(但不是杰森),所以我做的变化在Fedor的代码,下面是我的实现,希望这有助于

LazyAdapter

public LazyAdapter(Activity a, ArrayList<?> mStatus)
{
    activity = a;
    data = mStatus;
    inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    imageLoader = new ImageLoader(activity.getApplicationContext());
}
public int getCount()
{
    if(data != null  && data.size() > 15)
        return data.size();
    else
        return 15;
}

我发现,即使文件在sd卡它不加载,因为它检查的对象是空的,如果你改变活动上的列表实现,所以我改变了getBitmap()代码也 ImageLoader

private Bitmap getBitmap(String urlString)
{
    String filename = String.valueOf(urlString.substring(urlString.lastIndexOf("/") + 1));
    File f = new File(cacheDir, filename);
    try
    {
        if(!f.exists())
        {
            Bitmap bitmap = null;
            InputStream is = new URL(urlString).openStream();
            OutputStream os = new FileOutputStream(f);
            Globals.CopyStream(is, os);
            os.close();
            bitmap = decodeFile(f);
            return bitmap;
        }
        else
        {               
            Bitmap bitmap = decodeFile(f);
            return bitmap;
        }
    }
    catch (Exception ex)
    {
        ex.printStackTrace();
        BitmapDrawable mDrawable = (BitmapDrawable) context.getResources().getDrawable(R.drawable.placeholder);
        return mDrawable.getBitmap();
    }
}

Stackoverflow成员Fedor发布了一些缓存ImageLoader的源代码来回答这个问题。Android -如何在ListView中延迟加载图片。他的回答得到了100多个赞。我发现它可以很好地缓存我的Flickr图片。

在发送到惰性加载器类时还没有设置图像标记。

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

什么是私有ImageThreadLoader imageLoader = new ImageThreadLoader();? 我能看看那堂课吗?

最新更新