ListView的Lazy Image Loader

时间:2012-03-07 09:56:18

标签: android listview

好吧,我用这个项目作为我项目的起点: https://github.com/thest1/LazyList/

而不是他的LazyAdapter,我使用了我制作的一个,以下:

public class CardAdapter extends ArrayAdapter<Card> {
    private Card[] cards;
    private Context context;
    private LayoutInflater mInflater; 
    public ImageLoader imageLoader; 


    public CardAdapter (Context context, int textViewResourcesId, Card[] cards)
    {
        super(context, textViewResourcesId, cards);
        this.cards = cards;
        this.context = context;
        mInflater = LayoutInflater.from(context);  
    }

    private static class ViewHolder {  
        public ImageView iconView;  
        public TextView nameTextView;  
        public TextView descText;
        public TextView manaText;
        public TextView atkdef;
        public TextView edicao;
        public TextView tipo;
    }  

    @Override  
    public View getView(int position, View convertView, ViewGroup parent) 
    {  
        ViewHolder holder;  
        if (convertView == null) {  
            convertView = mInflater.inflate(R.layout.listrow, parent, false); 
        TextView nameTextView = (TextView) convertView  
                    .findViewById(R.id.Nome);  
            TextView descText = (TextView) convertView  
                    .findViewById(R.id.descricao);  
            TextView manaText = (TextView) convertView  
                    .findViewById(R.id.mana);
            TextView atkdef = (TextView) convertView
            .findViewById(R.id.atkdef);
            TextView edicao = (TextView) convertView
                .findViewById(R.id.edicao);
            TextView tipo = (TextView) convertView
                .findViewById(R.id.tipo);
            ImageView iconView = (ImageView) convertView  
                    .findViewById(R.id.imageView1);

            holder = new ViewHolder();
            holder.nameTextView = nameTextView;
            holder.descText = descText;
            holder.manaText = manaText;
            holder.atkdef = atkdef;
            holder.edicao = edicao;
            holder.tipo = tipo;
            holder.iconView = iconView;  
            holder.iconView.setTag(cards[position].URL);

            convertView.setTag(holder);  
        } else {  
            holder = (ViewHolder) convertView.getTag();  
        }  

        holder.nameTextView.setText(cards[position].name);                                          holder.descText.setText(setSpanOnText(cards[position].descricao),BufferType.SPANNABLE);
        holder.manaText.setText(setSpanOnManaText(cards[position].mana), BufferType.SPANNABLE);
        if (cards[position].tipo.toLowerCase().contains("creature"))
            holder.atkdef.setText(cards[position].power + "/" + cards[position].toughness);
        else
            holder.atkdef.setText("");
        holder.edicao.setText("Edition: " + cards[position].edicao);
        holder.tipo.setText(cards[position].tipo); 
        holder.iconView.setTag(cards[position].URL);  
        imageLoader.DisplayImage(cards[position].URL, holder.iconView);
        return convertView;  
    }  
}

它运作良好,直到我添加“imageLoader.DisplayImage(cards [position] .URL,holder.iconView);”这是懒惰的负载部分,当我尝试访问列表视图时,它开始崩溃,有人有想法吗?我在其他项目的ImageLoader / FileCache / MemoryCache / Utils中没有改变...

感谢您的建议!

2 个答案:

答案 0 :(得分:0)

之前我使用过这个懒惰加载程序代码,并且它正在尝试访问您的SD卡,因此请确保在清单中设置正确的权限。

此外,您不应该访问ListView,只需访问与标记对应的ImageView。你确定你做得对吗?您可能需要使用此类发布代码。

在ListView中使用它的正确方法是:

imageView.setTag(image_url);
imageLoader.DisplayImage(image_url, imageView);
按顺序

答案 1 :(得分:0)

    package com.jaapp;

    import java.util.ArrayList;

    import android.app.Activity;
    import android.app.ProgressDialog;
    import android.content.Context;
    import android.content.Intent;
    import android.graphics.Color;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.ImageView;
    import android.widget.ListView;
    import android.widget.TextView;

    import com.jaapp.application.JaappApplication;
    import com.jaapp.db.Jaappdb;
    import com.jaapp.dto.SubtypeDto;
    import com.jaapp.lazyloader.ImageLoader;

    public class SubTypeActivity extends Activity {

        ArrayList<SubtypeDto> arrylistsubtype = new ArrayList<SubtypeDto>();
        ListView list;

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            setContentView(R.layout.subtype);
            new subtypeAsyncTask().execute();

        }

        public class subtypeAsyncTask extends AsyncTask<Void, Void, Void> {
            private ProgressDialog progrssdilaog;

            @Override
            protected void onPreExecute() {

                progrssdilaog = ProgressDialog.show(SubTypeActivity.this,
                        "Please wait", "Loading Data ...", true);

            }

            @Override
            protected Void doInBackground(Void... params) {

                arrylistsubtype = Jaappdb.getSubtypeDtos();

                return null;
            }

            @Override
            protected void onPostExecute(Void result) {

                progrssdilaog.dismiss();

                list = (ListView) findViewById(R.id.list);
                list.setAdapter(new Listadatper(SubTypeActivity.this,
                        arrylistsubtype));

            }

        }

        public class Listadatper extends BaseAdapter {
            private Activity activity;

            public ImageLoader imageLoader;

            ArrayList<SubtypeDto> mlist;

            public int[] selected;
            public int countcolor = 0;

            public int i = 0;
            public String[] Colorname = { "#FFFF00", "#ACCC00" };

            public Listadatper(SubTypeActivity secondActivity,
                    ArrayList<SubtypeDto> arrylistsubtype) {

                this.activity = secondActivity;
                mlist = arrylistsubtype;

                selected = new int[mlist.size()];

                for (int i = 0; i < mlist.size(); i++) {
                    selected[i] = 0;
                }

            }

            public View getView(final int position, View convertView,
                    ViewGroup parent) {

                LayoutInflater inflater = (LayoutInflater) activity
                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

                View gridView;

                gridView = inflater.inflate(R.layout.list_row, null);

                TextView txt_name = (TextView) gridView
                        .findViewById(R.id.txt_entrepreneur);

                ImageView img_icon = (ImageView) gridView
                        .findViewById(R.id.img_entrepreneur);
                txt_name.setText(mlist.get(position).getName());

                imageLoader = new ImageLoader(activity.getApplicationContext());
                imageLoader.DisplayImage(getString(R.string.imagelink) + mlist.get(position).getLogo(), activity, img_icon);
                if(position % 2 == 0) {
                    gridView.setBackgroundColor(Color.parseColor(Colorname[0]));
                } else {
                    gridView.setBackgroundColor(Color.parseColor(Colorname[1]));
                }

                gridView.setOnClickListener(new OnClickListener() {

                    @Override
                    public void onClick(View v) {

                        Intent i = new Intent(SubTypeActivity.this,
                                SubOptionTypeActivity.class);
                        JaappApplication.subtypeid = mlist.get(position).getId();
                        startActivity(i);

                    }
                });

                return gridView;
            }

            @Override
            public int getCount() {
                return mlist.size();
            }

            @Override
            public Object getItem(int position) {
                return null;
            }

            @Override
            public long getItemId(int position) {
                return 0;
            }

        }

    }


    ------------------------------------------------------------------------------------------
    package com.jaapp.lazyloader;

    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;

    import com.jaapp.R;


    public class ImageLoader {

        private HashMap<String, Bitmap> cache=new HashMap<String, Bitmap>();

        private File cacheDir;

        public ImageLoader(Context context){

            photoLoaderThread.setPriority(Thread.NORM_PRIORITY-1);


            if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
                cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"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)
        {
             photosQueue.Clean(imageView);
            PhotoToLoad p=new PhotoToLoad(url, imageView);
            synchronized(photosQueue.photosToLoad){
                photosQueue.photosToLoad.push(p);
                photosQueue.photosToLoad.notifyAll();
            }

            if(photoLoaderThread.getState()==Thread.State.NEW)
                photoLoaderThread.start();
        }

        private Bitmap getBitmap(String url) 
        {

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

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

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

    }
    ------------------------------------------------------------------------------------------
    package com.jaapp.lazyloader;

    import java.io.InputStream;
    import java.io.OutputStream;

    public class Utils {
        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){}
        }
    }