Android自定义适配器列表查看滚动时随机显示的图像

时间:2014-01-11 17:22:39

标签: android android-listview android-asynctask custom-adapter

您好我是Android的菜鸟,我正在尝试使用自定义适配器将一些数据加载到ListView。我使用以下代码加载数据。第一次,它运作良好。但是当我尝试加载更多时,数据加载和图像在滚动时显示随机。在该列表中显示一些随机图像后,最终显示正确的图像。它也在下一个卷轴上重复

这是我的getView代码

 @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;
        final ViewHolder holder;
        if (v == null) {
            LayoutInflater vi =
                (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = vi.inflate(R.layout.review_list_m, null);
            v.setMinimumHeight(height);
            holder = new ViewHolder();
            holder.item1 = (TextView) v.findViewById(R.id.name);
            holder.image = (ImageView) v.findViewById(R.id.posterView);
            v.setTag(holder);
        }
        else
            holder=(ViewHolder)v.getTag();

        int colorPos = position % colors.length;
        v.setBackgroundColor(Color.parseColor(colors[colorPos]));


        final Custom custom = entries.get(position);
        if (custom != null) {
            holder.image.setBackgroundColor(Color.parseColor(colors[colorPos]));
            holder.image.setLayoutParams(new LinearLayout.LayoutParams(height-10,width-10));
            String imgUrl=custom.getImage();

            AsyncHttpClient client = new AsyncHttpClient();
              String[] allowedContentTypes = new String[] { "image/png", "image/jpeg" };
              client.get(imgUrl, new BinaryHttpResponseHandler(allowedContentTypes) {
                  @Override
                  public void onSuccess(byte[] fileData) {
                      // Do something with the file
                      ByteArrayInputStream inputStream = new ByteArrayInputStream(fileData);
                      Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                      holder.image.setImageBitmap(bitmap);
                  }
              });

              holder.item1.setHeight(height/3);
            Log.v("PATH",custom.getcustomBig());
            holder.item1.setText(custom.getcustomBig());

        }
        return v;
    }

有什么想法吗?请帮忙

更新

   @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;
        final ViewHolder holder;
        if (v == null) {
            LayoutInflater vi =
                (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = vi.inflate(R.layout.review_list_m, null);
            v.setMinimumHeight(height);
            holder = new ViewHolder();
            holder.item1 = (TextView) v.findViewById(R.id.name);
            holder.image = (ImageView) v.findViewById(R.id.posterView);
            v.setTag(holder);
        }
        else
            holder=(ViewHolder)v.getTag();

        int colorPos = position % colors.length;
        v.setBackgroundColor(Color.parseColor(colors[colorPos]));


        final Custom custom = entries.get(position);
        if (custom != null) {
            holder.image.setBackgroundColor(Color.parseColor(colors[colorPos]));
            holder.image.setLayoutParams(new LinearLayout.LayoutParams(height-10,width-10));
            final String imgUrl=custom.getImage();
            holder.image.setTag(imgUrl);


            holder.image.setImageBitmap(null);
            Bitmap cachedBitmap = cache.get(imgUrl);
            if( cachedBitmap == null) {

                Log.v("HERE","DOWNLOADING");
                AsyncHttpClient client = new AsyncHttpClient();
              String[] allowedContentTypes = new String[] { "image/png", "image/jpeg" };
              client.get(imgUrl, new BinaryHttpResponseHandler(allowedContentTypes) {
                  @Override
                  public void onSuccess(byte[] fileData) {
                      // Do something with the file
                      ByteArrayInputStream inputStream = new ByteArrayInputStream(fileData);
                      Bitmap bitmap = BitmapFactory.decodeStream(inputStream);

                       holder.image.setImageBitmap(bitmap);
                                      }
              });
            }
            else 
            {
                holder.image.setImageBitmap(cachedBitmap);
            }

              holder.item1.setHeight(height/3);
            //Log.v("PATH",custom.getcustomBig());
            holder.item1.setText(custom.getcustomBig());

        }

3 个答案:

答案 0 :(得分:1)

如果v!= null,可以将null位图设置为holder.image。否则,Android可以显示来自其他单元格的位图,直到通过异步http请求下载新图像。

示例代码(有关重新下载图片的问题),它不是睾丸,但应该让您知道它应该是什么样的:

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

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

    //....

    final Custom custom = entries.get(position);
    if (custom != null) {
        holder.image.setBackgroundColor(Color.parseColor(colors[colorPos]));
        holder.image.setLayoutParams(new LinearLayout.LayoutParams(height-10,width-10));
        String imgUrl=custom.getImage();

        Bitmap cachedBitmap = cache.get(imgUrl);

        if( cachedBitmap == null) {
            AsyncHttpClient client = new AsyncHttpClient();
            String[] allowedContentTypes = new String[] { "image/png", "image/jpeg" };
            client.get(imgUrl, new BinaryHttpResponseHandler(allowedContentTypes) {
                @Override
                public void onSuccess(byte[] fileData) {
                    // Do something with the file
                    ByteArrayInputStream inputStream = new ByteArrayInputStream(fileData);
                    Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                    holder.image.setImageBitmap(bitmap);
                    cache.add( imgUrl, bitmap );
                }
            });
        }
        else 
        {
            holder.image.setImageBitmap(cachedBitmap);
        }

        holder.item1.setHeight(height/3);
        Log.v("PATH",custom.getcustomBig());
        holder.item1.setText(custom.getcustomBig());
    }

答案 1 :(得分:0)

编辑回答 在设置位图之前,验证您的imageview标签没有更改。 你可以尝试:

    /**
 * Caches an image (or a group of them) async.
 * @author 
 *
 */
public static class ImageCacher extends AsyncTask<String, String, Integer>{

    Context context;
    ImageView iv;
    Bitmap b;


    public ImageCacher(Context context, ImageView iv){
        this.context = context;
        this.iv = iv;
    }

    @Override
    protected Integer doInBackground(String... params) {

        for(final String param:params){
            //check if already CACHED
            String filename = String.format("%d", param.hashCode());
            File file = new File(context.getFilesDir(), filename);
            if(file.exists()){
                try {
                    b = BitmapFactory.decodeFile(file.getAbsolutePath());
                } catch (Exception e) {
                }
                if(b != null){
                    if(iv != null){
                        iv.post(new Runnable() {

                            public void run() {
                                String tag = (String) iv.getTag();
                                if(tag != null){
                                    if(tag.matches(param))
                                        iv.setImageBitmap(b);
                                }

                            }
                        });
                    }

                    return 0;
                }else{
                    file.delete();
                }
            }

            //download
            file = new File(context.getFilesDir(), filename);
            b = saveImageFromUrl(context, param);
            if(b != null){
                if(iv != null){
                    iv.post(new Runnable() {

                        public void run() {
                            String tag = (String) iv.getTag();
                            if(tag != null){
                                if(tag.matches(param))
                                    iv.setImageBitmap(b);
                            }

                        }
                    });
                }
            }
        }

        return 0;
    }

}

/**
 * Gets an image given its url
 * @param param
 */
public static Bitmap saveImageFromUrl(Context context, String fullUrl) {
    Bitmap b = null;

    try {
        URL url = new URL(fullUrl);
        URLConnection conn = url.openConnection();
        conn.setDoInput(true);
        conn.connect();
        //save bitmap to file
        InputStream is = conn.getInputStream();
        String filename = String.format("%d", fullUrl.hashCode());
        File file = new File(context.getFilesDir(), filename);
        if(file.exists()){
            //delete
            file.delete();
            file=null;
        }
        file = new File(context.getFilesDir(), filename);

        FileOutputStream out = new FileOutputStream(file);
        byte buffer[] = new byte[256];
        while(true){
            int cnt = is.read(buffer);
            if(cnt <=0){
                break;
            }
            out.write(buffer,0, cnt);
        }

        out.flush();
        out.close();
        is.close();

        b = BitmapFactory.decodeFile(file.getAbsolutePath());

    } catch (Exception e) {
        e.printStackTrace();
    }

    return b;
}

/**
 * Gets an already cached photo
 * 
 * @param context
 * @param fullUrl
 * @return
 */
public static Bitmap getCachedPhoto(Context context, String fullUrl){
    System.gc();
    String filename = String.format("%d", fullUrl.hashCode());
    File file = new File(context.getFilesDir(), filename);
    if(file.exists()){
        try {
            Bitmap b = BitmapFactory.decodeFile(file.getAbsolutePath());
            return b;
        } catch (Exception e) {
        }
    }

    return null;
}

然后,要在适配器中设置图像,您可以这样做:

//set info
    vh.iv.setTag("");
    String foto = your_url_goes_here;
    vh.iv.setImageResource(R.drawable.fotodefault_2x);
    if(!TextUtils.isEmpty(foto)){
        vh.iv.setTag(foto);
        Bitmap b = getCachedPhoto(context, foto);
        if(b != null){
            vh.iv.setImageBitmap(b);
        }else{
            new ImageCacher(context, vh.iv).execute(foto);
        }
    }

不要忘记正确封装类和方法。 希望它有所帮助。

答案 2 :(得分:0)

我的arrayAdapter出现了这个随机图片问题。然后我使用了Picasso,它负责在listview中重用imageView:http://square.github.io/picasso/

代码示例:

    Picasso.with(mContext)
            .load(url)
            .resize(size, size)
            .centerCrop()
            .placeholder(R.drawable.image_holder)
            .into(holder.imgDefaultImage);