listview和Asynctask的图像问题

时间:2013-11-14 16:22:03

标签: android listview android-listview android-asynctask

我正在使用listview,每个项目都使用从带有asynctask类的服务器调用的图像。

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
        View view = convertView;
        final ViewHolder viewHolder;

        if (view == null) {
            view = getActivity().getLayoutInflater().inflate(R.layout.item_liste, null);
            viewHolder = new ViewHolder();
            viewHolder.image = (ImageView) view.findViewById(R.id.imageView);
            view.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) view.getTag();
        }

        if (/* Image not loaded */) {

            /* Create and execute the request using an AsyncTask */
            mRequestManager.getDrawable("0", listItemInformation.resumeBien.Identifiant, new SendBitmap() {

                /* SendBack is called when the bitmap is received from the server */

                @Override
                public void sendBack(Bitmap bitmap) {
                    listItemInformation.drawable.add(bitmap);
                    listItemInformation.drawableCalled = false;
                    viewHolder.image.setImageBitmap(bitmap);
                } 
           });
        } else {
            viewHolder.image.setImageBitmap(listItemInformation.drawable.get(0));
        }

        return view;
    }

问题是,当收到图像时,ImageView不是好的。 所有图片都加载到列表视图的第一项..

我尝试使用adapter.notifyDataSetChanged();

但是在滚动期间调用listview动作时会被剪切..

我有什么机会避免这些问题? 我想要与googleplay的列表视图相同的结果。

提前致谢:)

2 个答案:

答案 0 :(得分:2)

只需一两行就可以试用Volley的NetworkImageView来完成你的工作。

     //Dummy:

    public static class BitmapLruCache extends LruCache<String, Bitmap> implements ImageCache {

    public BitmapLruCache(int maxSize) {
        super(maxSize);
    }


    @Override
    protected int sizeOf(String key, Bitmap value) {
        return value.getRowBytes() * value.getHeight();
    }


    @Override
    public Bitmap getBitmap(String url) {
        return get(url);
    }


    @Override
    public void putBitmap(String url, Bitmap bitmap) {
        put(url, bitmap);
    }
  }

    ImageLoader sImageLoader = new ImageLoader(sRequestQueue, new BitmapLruCache(100));

    networkImageView.setImageUrl(url_to_image, sImageLoader);

答案 1 :(得分:1)

你需要什么称为“懒惰适配器”,要在列表视图中加载图像,你可以尝试我的代码:

public class MainActivity extends Activity {

ListView list;
LazyAdapter adapter;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    list=(ListView)findViewById(R.id.list);
    adapter=new LazyAdapter(this, mStrings);
    list.setAdapter(adapter);
    adapter.imageLoader.clearCache();
    adapter.notifyDataSetChanged();

    list.setOnItemClickListener(new AdapterView.OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                                int position, long id) {
            //Toast.makeText(getApplicationContext(), id + "", 2000).show();
            String wallcategory =(String) ((TextView) view.findViewById(R.id.text)).getText();
            //Toast.makeText(getApplicationContext(),mStrings[position], 2000).show();


            Intent myIntent = new Intent(MainActivity.this, Wallgrid.class);
           myIntent.putExtra("cat", wallcategory); //Optional parameters
            MainActivity.this.startActivity(myIntent);


        }
    });
}

@Override
public void onDestroy()
{
    list.setAdapter(null);
    super.onDestroy();
}



public String[] mStrings={
        "http://www.bourax.com/android/paradise/categories/nature.jpg",
        "http://www.bourax.com/android/paradise/categories/animals.jpg",
        "http://www.bourax.com/android/paradise/categories/colorful.jpg",
        "http://www.bourax.com/android/paradise/categories/cars.jpg",
        "http://www.bourax.com/android/paradise/categories/city.jpg",
        "http://www.bourax.com/android/paradise/categories/flowers.jpg",
        "http://www.bourax.com/android/paradise/categories/girls.jpg",
        "http://www.bourax.com/android/paradise/categories/sport.jpg",
        "http://www.bourax.com/android/paradise/categories/cats.jpg",
        "http://www.bourax.com/android/paradise/categories/fish.jpg",
        "http://www.bourax.com/android/paradise/categories/sea.jpg",
        "http://www.bourax.com/android/paradise/categories/love.jpg",
        "http://www.bourax.com/android/paradise/categories/buildings.jpg",
        "http://www.bourax.com/android/paradise/categories/paintings.jpg",
        "http://www.bourax.com/android/paradise/categories/pink.jpg",
        "http://www.bourax.com/android/paradise/categories/travel.jpg",
        "http://www.bourax.com/android/paradise/categories/fantasy.jpg",
        "http://www.bourax.com/android/paradise/categories/tree.jpg",
        "http://www.bourax.com/android/paradise/categories/portrait.jpg",
        "http://www.bourax.com/android/paradise/categories/top.jpg"



};

}

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 String[] Category={
        "Nature",
        "Animals",
        "Colorful",
        "Cars",
        "City",
        "Flowers",
        "Girls",
        "Sport",
        "Cats & Dogs",
        "Fish",
        "Sea",
        "Love",
        "Buildings",
        "Paintings",
        "Pink",
        "Travel",
        "Fantasy",
        "Tree",
        "Portrait",
        "Top Rated"


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

    View vi=convertView;
    if(convertView==null)
        vi = inflater.inflate(R.layout.item, null);

    TextView text=(TextView)vi.findViewById(R.id.text);
    ImageView image=(ImageView)vi.findViewById(R.id.image);
    text.setText(Category[position]);
    imageLoader.DisplayImage(data[position], image);
    return vi;
}
}




 public class ImageLoader {

MemoryCache memoryCache=new MemoryCache();
FileCache fileCache;
private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
ExecutorService executorService;
Handler handler=new Handler();//handler to display images in UI thread

public ImageLoader(Context context){
    fileCache=new FileCache(context);
    executorService=Executors.newFixedThreadPool(5);
}

final int stub_id=R.drawable.stub;
public void DisplayImage(String url, ImageView imageView)
{
    imageViews.put(imageView, url);
    Bitmap bitmap=memoryCache.get(url);
    if(bitmap!=null)
        imageView.setImageBitmap(bitmap);
    else
    {
        queuePhoto(url, imageView);
        //imageView.setImageResource(stub_id);
    }
}

private void queuePhoto(String url, ImageView imageView)
{
    PhotoToLoad p=new PhotoToLoad(url, imageView);
    executorService.submit(new PhotosLoader(p));
}

private Bitmap getBitmap(String url) 
{
    File f=fileCache.getFile(url);

    //from SD cache
    Bitmap b = decodeFile(f);
    if(b!=null)
        return b;

    //from web
    try {
        Bitmap bitmap=null;
        URL imageUrl = new URL(url);
        HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
        conn.setConnectTimeout(30000);
        conn.setReadTimeout(30000);
        conn.setInstanceFollowRedirects(true);
        InputStream is=conn.getInputStream();
        OutputStream os = new FileOutputStream(f);
        Utils.CopyStream(is, os);
        os.close();
        conn.disconnect();
        bitmap = decodeFile(f);
        return bitmap;
    } catch (Throwable ex){
       ex.printStackTrace();
       if(ex instanceof OutOfMemoryError)
           memoryCache.clear();
       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;
        FileInputStream stream1=new FileInputStream(f);
        BitmapFactory.decodeStream(stream1,null,o);
        stream1.close();

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

        //decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize=scale;
        FileInputStream stream2=new FileInputStream(f);
        Bitmap bitmap=BitmapFactory.decodeStream(stream2, null, o2);
        stream2.close();
        return bitmap;
    } catch (FileNotFoundException e) {
    } 
    catch (IOException e) {
        e.printStackTrace();
    }
    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;
    }
}

class PhotosLoader implements Runnable {
    PhotoToLoad photoToLoad;
    PhotosLoader(PhotoToLoad photoToLoad){
        this.photoToLoad=photoToLoad;
    }

    @Override
    public void run() {
        try{
            if(imageViewReused(photoToLoad))
                return;
            Bitmap bmp=getBitmap(photoToLoad.url);
            memoryCache.put(photoToLoad.url, bmp);
            if(imageViewReused(photoToLoad))
                return;
            BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad);
            handler.post(bd);
        }catch(Throwable th){
            th.printStackTrace();
        }
    }
}

boolean imageViewReused(PhotoToLoad photoToLoad){
    String tag=imageViews.get(photoToLoad.imageView);
    if(tag==null || !tag.equals(photoToLoad.url))
        return true;
    return false;
}

//Used to display bitmap in the UI thread
class BitmapDisplayer implements Runnable
{
    Bitmap bitmap;
    PhotoToLoad photoToLoad;
    public BitmapDisplayer(Bitmap b, PhotoToLoad p){bitmap=b;photoToLoad=p;}
    public void run()
    {
        if(imageViewReused(photoToLoad))
            return;
        if(bitmap!=null)
            photoToLoad.imageView.setImageBitmap(bitmap);
       // else
           // photoToLoad.imageView.setImageResource(stub_id);
    }
}

public void clearCache() {
    memoryCache.clear();
    fileCache.clear();
}

}



 public class FileCache {

private File cacheDir;

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

public File getFile(String url){
    //I identify images by hashcode. Not a perfect solution, good for the demo.
    String filename=String.valueOf(url.hashCode());
    //Another possible solution (thanks to grantland)
    //String filename = URLEncoder.encode(url);
    File f = new File(cacheDir, filename);
    return f;

}

public void clear(){
    File[] files=cacheDir.listFiles();
    if(files==null)
        return;
    for(File f:files)
        f.delete();
}

}