【问题标题】:Gridview images changes/shuffle on scrollGridview 图像在滚动时更改/随机播放
【发布时间】:2014-10-25 08:37:39
【问题描述】:

我有一个带有自定义 arrayadapter 的 gridview。 在滚动图像时随机播放。我确定适配器有问题。我错过了一些东西。我已经发布了适配器的代码。

公共类 CustomAdapterForDealsGrid 扩展 ArrayAdapter{

private  final boolean checkBoxState[] ;

private TCLruCache cache;

Context context;
int layoutResourceId;
private BtnClickListener mClickListener = null;
private OnClickListener clickListner = null;


ArrayList<Ads> data = new ArrayList<Ads>();
Map<String,Bitmap> imageMap = new HashMap<String, Bitmap>();

public CustomAdapterForDealsGrid(Context context, int resource,
        ArrayList<Ads> objects,BtnClickListener listener) {
    super(context, resource, objects);

    ActivityManager am = (ActivityManager) context.getSystemService(
            Context.ACTIVITY_SERVICE);
        int memoryClass = am.getMemoryClass() * 1024 * 1024;
        cache = new TCLruCache(memoryClass);

    this.layoutResourceId = resource;
    this.context = context;
    this.data = objects;
    checkBoxState=new boolean[this.data.size()];

    mClickListener = listener;
    //new GetImageAsync().execute();
}

 private class GetImageAsync extends AsyncTask<Void, Void, Boolean> {

    @Override
    protected Boolean doInBackground(Void... arg0) {

        setImageMap();  
        return null;
    }

 }
public void setImageMap(){
    for(Ads ads : data){
        try {
            imageMap.put("http://"+ApplicationConstant.host+ "/"+ads.getImagepath(),getImageFromUrl("http://"+ApplicationConstant.host+ "/"+ads.getImagepath()));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

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

@Override
public Ads getItem(int item) {
    return data.get(item);
}

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




@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    View row = convertView;
    DealHolder holder = null;


    if (row == null) {
        LayoutInflater inflater = ((Activity) context).getLayoutInflater();
        row = inflater.inflate(layoutResourceId, parent, false);

        holder = new DealHolder();
        holder.imageItem = (ImageView) row.findViewById(R.id.item_deal);
        holder.txtURL =(TextView) row.findViewById(R.id.item_url);
        holder.txtDesc =(TextView) row.findViewById(R.id.item_desc);
        holder.chkGrid = (CheckBox)row.findViewById(R.id.chkGrid);
        holder.txtPrice =(TextView) row.findViewById(R.id.item_price);

        holder.button = (Button) row.findViewById(R.id.btnDeal);
        holder.button.setTag(Integer.valueOf(position));
        holder.button.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                if(mClickListener != null)
                    mClickListener.onBtnClick((Integer)v.getTag());                

            }
        });
        row.setTag(holder);
    } else {
        holder = (DealHolder) row.getTag();
    }

    if(holder.setFlag!=true){
    Ads ads = data.get(position);

    holder.imageItem.setImageResource(R.drawable.powerelectronics);
    holder.txtPrice.setText(ads.getPricerange());
    holder.txtURL.setText(ads.getUrl());
    holder.txtDesc.setText(ads.getDesc());
    holder.chkGrid.setChecked(checkBoxState[position]);
            holder.chkGrid.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {


                           if(((CheckBox)v).isChecked()){
                               checkBoxState[position]=true;
                               data.get(position).setChecked(true);
                           }else{
                               checkBoxState[position]=false;
                               data.get(position).setChecked(false);
                           }

                }

                }
            );

    try {
        if(cache.get("http://"+ApplicationConstant.host+ "/"+ads.getImagepath()) != null){
            holder.imageItem.setImageBitmap(cache.get("http://"+ApplicationConstant.host+ "/"+ads.getImagepath()));
        }
        else{
BitmapFactory.decodeResource(context.getResources(),        R.drawable.abs__activated_background_holo_light));
        setBitmap(holder.imageItem, "http://"+ApplicationConstant.host+ "/"+ads.getImagepath(),ads.getDesc());
        }
        holder.setFlag = true;

    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    }
    return row;

}

static class DealHolder {
    TextView txtPrice,txtURL,txtDesc;
    ImageView imageItem;
    Button button;
    CheckBox chkGrid;
    Boolean setFlag = new Boolean(false);

}


public Bitmap getImageFromUrl(String imgPath) throws Exception{
 HttpGet httpRequest = null;
 URL url = new URL(imgPath);

 httpRequest = new HttpGet(url.toURI());

 HttpClient httpclient = new DefaultHttpClient();
 HttpResponse response = (HttpResponse) httpclient
         .execute(httpRequest);

 HttpEntity entity = response.getEntity();
 BufferedHttpEntity b_entity = new BufferedHttpEntity(entity);
 InputStream input = b_entity.getContent();

 Bitmap bitmap = BitmapFactory.decodeStream(input);
 return bitmap;
}

private Bitmap methodScaledImage(int width,int height,Bitmap origBitmap) throws FileNotFoundException{

Bitmap background = Bitmap.createBitmap((int)width, (int)height, Config.ARGB_8888);
float originalWidth = origBitmap.getWidth(), originalHeight = origBitmap.getHeight();
Canvas canvas = new Canvas(background);
float scale = width/originalWidth;
float xTranslation = 0.0f, yTranslation = (height - originalHeight * scale)/2.0f;
Matrix transformation = new Matrix();
transformation.postTranslate(xTranslation, yTranslation);
transformation.preScale(scale, scale);
Paint paint = new Paint();
paint.setFilterBitmap(true);
canvas.drawBitmap(origBitmap, transformation, paint);
return background;
}



private void setBitmap(final ImageView iv, final String path,final String desc) {

new AsyncTask<Void, Void, Bitmap>() {

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

        Bitmap imageBtMP= null;
        try {
            imageBtMP = getImageFromUrl(path);
            if(imageBtMP!= null){
                cache.put(path, imageBtMP);
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return imageBtMP;
    }

    @Override
    protected void onPostExecute(Bitmap result) {
        super.onPostExecute(result);
        iv.setImageBitmap(result);

        iv.setOnClickListener(new OnClickListener() {


            public void onClick(View v) {


                LayoutInflater layoutInflater = LayoutInflater.from(getContext());
               View popupView = layoutInflater.inflate(R.layout.activity_desc_deal, null);  
                        final PopupWindow popupWindow = new PopupWindow(
                          popupView, 
                          LayoutParams.WRAP_CONTENT,  
                                LayoutParams.WRAP_CONTENT);  

                        final TextView descTextview = (TextView) popupView.findViewById(R.id.descdeal);
                        descTextview.setText(desc);


                        Button btnDismiss = (Button)popupView.findViewById(R.id.dismiss);
                        btnDismiss.setOnClickListener(new Button.OnClickListener(){

                @Override
                public void onClick(View v) {
                 // TODO Auto-generated method stub
                 popupWindow.dismiss();
                }});

                        popupWindow.showAsDropDown(v, 50, -30);


            }
        });

    }
}.execute();
}
private class TCLruCache extends LruCache<String, Bitmap> {


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

}

【问题讨论】:

  • 当我把它改成@Override public long getItemId(int position) { return 0; } 滚动后图像相同。我是否在覆盖函数中遗漏了一些东西

标签: android gridview android-arrayadapter


【解决方案1】:

看起来问题出在您的 setBitmap() 方法上。在整个异步过程中,绝对不能保证您传入的ImageViewonPostExecute() 中的Bitmap 相同。这是由于 View 回收适配器所做的。此外,您必须将 ImageView 存储为 WeakReference。否则你有泄露它的风险。

你的异步应该更像这样:

private class ExampleAsync extends AsyncTask<Void, Void, Bitmap> {
    private WeakReference<ImageView> mImageViewRef;
    private String mPath;
    private String mDesc;

    public ExampleAsync(ImageView iv, String path, String desc) {
        iv.setTag(path);    //Records which path the ImageView represents
        mImageViewRef = new WeakReference<ImageView>(iv);
        mPath = path;
        mDesc = desc;
    }

    @Override
    protected Bitmap doInBackground(Void... params) {
        ImageView iv = mImageViewRef.get();
        if (iv == null || !mPath.equals(iv.getTag())) {
            return null;
        }

        //Retrieve bitmap logic. Return results or null if it fails
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {
        ImageView iv = mImageViewRef.get();
        if (iv == null || bitmap == null || !mPath.equals(iv.getTag())) {
            //In an invalid state or results had error. Ignore everything and just exit Async.
            return;
        }

        //Received valid results and in good state. Set ImageView and do all your other logic
    }
}

这只是一个粗略的草图,但应该能够理解重点。这将处理使用适配器和/或在用户滚动期间呈现视图的不同结果。当ImageView 被回收并用于不同的位置时,记录ImageView 标记内的路径。存储在 WeakReference 中可确保被销毁的 ImageView 实际上可以被销毁。否则,您将保留参考并继续加载并将Bitmap 放入其中。您总是检查引用以确保 View 没有被破坏。使用时,总是临时存储在一个局部变量中,防止被GCed。

【讨论】:

  • 我已经用弱引用实现了你给的登录。我仍然遇到同样的问题。缓存是否导致问题? @Jay Soyer
  • 你能发布更新的代码吗?另外,我不确定持有人中 setFlag 变量的意义,但我会删除它。您应该始终为 ViewHolder 视图重置文本视图和图像,而不是仅在未设置该标志时。
  • 我使用了通用图像加载器。它与通用罐一起工作正常。我试图实现我自己的代码,但它没有用,也不能在这上面投入太多时间。谢谢,您提到的观点帮助我理解了视图和加载。 setFlag 我用来检查图像是否已经加载。但我删除了它,因为它没有任何区别
  • 没用过,听说是个不错的库。很高兴您找到了解决方案。祝你好运!
  • 是的,很好。它做缓存,从 url 获取图像。将检查实现并更新此线程。谢谢杰
猜你喜欢
  • 2018-07-14
  • 1970-01-01
  • 2020-09-25
  • 2022-07-10
  • 2013-03-06
  • 1970-01-01
  • 2014-10-10
  • 2013-03-29
  • 2022-08-14
相关资源
最近更新 更多