代码之家  ›  专栏  ›  技术社区  ›  Genaut

自定义适配器重复

  •  0
  • Genaut  · 技术社区  · 10 年前

    我有这个CustomAdapter,用我的数据填充列表。问题是Imageview被下载和绘制了很多次。例子:

    我在服务器上搜索视频列表:

    (Video1) Title 1 Description 1
    
    (Video2) Title 2 Description 2
    
    (Video3) Title 3 Description 3
    
    ..
    

    当加载时,将加载Video1中的图像,然后在同一Imageview中加载Video2Image,然后再次为列表中的每个视频加载,与列表中的视频相同。当我滚动适配器时,再次下载所有图像。有一些方法可以解决这个问题,我不理解这个问题。

    自定义适配器.java

    public class CustomAdapter extends ArrayAdapter<Video> {
        // declaring our ArrayList of items
        private ArrayList<Video> objects;
    
        public CustomAdapter(Context context, int textViewResourceId, ArrayList<Video> objects) {
            super(context, textViewResourceId, objects);
            this.objects = objects;
        }
    
        public View getView(int position, View convertView, ViewGroup parent){
    
            View v = convertView;
    
            if (v == null) {
                LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                v = inflater.inflate(R.layout.list_row, null);
            }
    
            Video i = objects.get(position);
    
            if (i != null) {
    
                TextView title = (TextView) v.findViewById(R.id.title);
                TextView description = (TextView) v.findViewById(R.id.description);
                ImageView imagen = (ImageView) v.findViewById(R.id.list_image);
    
                title.setText(i.getTitulo());
                description.setText(i.getDescripcion());
    
                //Creamos imagen descargada y la seteamos
                new DownloadImageTask(imagen).execute(i.getUrlimagen());
                BitmapDrawable drawable = (BitmapDrawable) imagen.getDrawable();
                Bitmap bitmap = drawable.getBitmap();
                imagen.setImageBitmap(bitmap);
    
                Log.i("Debug", "Creando una imagen para: " + i.getTitulo());
    
                v.setTag(R.id.id_url, i.getUrl().trim());//1.Url
                v.setTag(R.id.id_titulo,i.getTitulo().trim());//2.Título
                v.setTag(R.id.id_video,i.getId().trim());//3.ID
    
            }
    
            return v;
    
        }
    
        private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
            ImageView bmImage;
    
            public DownloadImageTask(ImageView bmImage) {
                this.bmImage = bmImage;
            }
    
            protected Bitmap doInBackground(String... urls) {
                String urldisplay = urls[0];
                Bitmap mIcon11 = null;
                try {
                    InputStream in = new java.net.URL(urldisplay).openStream();
                    BitmapFactory BitmapFactory = null;
                    mIcon11 = BitmapFactory.decodeStream(in);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return mIcon11;
            }
    
            protected void onPostExecute(Bitmap result) {
                if(result!=null)
                    bmImage.setImageBitmap(result);
            }
        }
    
        public ArrayList getValues(){
            return objects;
        }
    
    }
    

    对不起,我的英语。

    3 回复  |  直到 10 年前
        1
  •  1
  •   Budius    10 年前

    我之前回答过这个问题,我再次为你回答:不要重新发明轮子!

    由于您现在看到的原因(以及内存管理、缓存管理等其他原因),图像下载/缓存是一件非常复杂的事情,所以只需使用一个有效的库即可。

    以下是您使用的代码 Picasso (我最喜欢的android图像下载库)

    public View getView(int position, View convertView, ViewGroup parent){
    
        View v = convertView;
    
        if (v == null) {
            LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = inflater.inflate(R.layout.list_row, null);
        }
    
        Video i = objects.get(position);
    
        if (i != null) {
    
            TextView title = (TextView) v.findViewById(R.id.title);
            TextView description = (TextView) v.findViewById(R.id.description);
            ImageView imagen = (ImageView) v.findViewById(R.id.list_image);
    
            title.setText(i.getTitulo());
            description.setText(i.getDescripcion());
    
            //Creamos imagen descargada y la seteamos
            Picasso
                .with(imagen.getContext())
                .load(i.getUrlimagen())
                .into(imagen);
    
            Log.i("Debug", "Creando una imagen para: " + i.getTitulo());
    
            v.setTag(R.id.id_url, i.getUrl().trim());//1.Url
            v.setTag(R.id.id_titulo,i.getTitulo().trim());//2.Título
            v.setTag(R.id.id_video,i.getId().trim());//3.ID
    
        }
    
        return v;
    
    }
    

    完成!该代码负责线程、缓存和取消。

    ps.:你应该多读一点regaring适配器和ViewHolder模式,你做得不对。

        2
  •  1
  •   Vidia    10 年前

    我不久前遇到过这个问题。如果您登录 getView() 当您滚动到屏幕末尾时,您将看到它被调用。这意味着图像在滚动时会被多次下载。

    要解决这个问题,您需要缓存位图。一旦有了缓存,每次调用getView时,首先查询缓存以查看图像是否已下载,如果图像不可用,则下载并将其添加到缓存中。

    此方法在Android开发人员中进行了解释(使用代码)。 http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

        3
  •  0
  •   Gabe Sechan    10 年前

    您的getview始终在创建DownloadImageTask。你不想这样做——你想检查一下你是否已经有了它,只有当你没有的时候才下载一个新的。