滚动列表时视图意外更改

时间:2014-01-01 06:41:15

标签: android listview

大家好,我在面对列表视图的膨胀时遇到了意想不到的问题。

我正在创建一个列表视图,其中我正在显示图像标题和缩略图。我们还可以显示音频文件缩略图,但仅提供图像类。

当我快速滚动列表时。它的观点改变了很多次。在我的适配器类下面,我使用AsynkTask类获取缩略图并将此缩略图设置为imageview。

public class AdapterForBooks extends ArrayAdapter<ModelFile> {

    List<ModelFile> list;
    Context context;
    WindowManager wm;
    Display display;
    int w;

    public AdapterForBooks(Context context, List<ModelFile> list) {
        super(context, R.layout.list_layout_home, list);
        // TODO Auto-generated constructor stub
        this.list = list;
        this.context = context;
        wm = (WindowManager) context
                .getSystemService(Context.WINDOW_SERVICE);
        display = wm.getDefaultDisplay();
        w = display.getWidth();

    }

    static class ViewHolder {
        TextView txtName;
        ImageView img;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        View view = null;
        if (convertView == null) {
            LayoutInflater inflter = (LayoutInflater) LayoutInflater
                    .from(context);
            view = inflter.inflate(R.layout.list_layout_home, null);
            final ViewHolder holder = new ViewHolder();
            holder.txtName = (TextView) view
                    .findViewById(R.id.textViewName);
            holder.img = (ImageView) view.findViewById(R.id.imageView);
            LayoutParams params = (LayoutParams) holder.img
                    .getLayoutParams();
            params.height = w / 4;
            params.width = w / 4;
            holder.img.setLayoutParams(params);
            view.setTag(holder);
        } else {
            view = convertView;
        }
        final ViewHolder holder = (ViewHolder) view.getTag();
        String name = list.get(position).getFileName();
        holder.txtName.setText(name);

        String filePath = list.get(position).getFilePath();
        // holder.img.setImageBitmap(Bitmap.createScaledBitmap(BitmapFactory.decodeFile(filePath),100,100,false));
        new SetThumbnail()
                .execute(new Thumbnail(holder, filePath, position));
        return view;
    }

    class Thumbnail {
        ViewHolder holder;
        String path;
        int position;

        public Thumbnail(ViewHolder holder, String path, int position) {
            this.holder = holder;
            this.path = path;
            this.position = position;
        }

        public ViewHolder getHolder() {
            return holder;
        }

        public String getPath() {
            return path;
        }

        public int getPosition() {
            return position;
        }

    }

    class SetThumbnail extends AsyncTask<Thumbnail, Void, Bitmap> {

        ViewHolder holder;

        int position;

        @Override
        protected Bitmap doInBackground(Thumbnail... params) {
            // TODO Auto-generated method stub
            int pos = params[0].getPosition();
            position = pos;
            String path = params[0].getPath();
            holder = params[0].getHolder();

            Log.e("Ref", "Pos = " + pos + " " + holder);
            try {
                Bitmap thumbnail = BitmapFactory.decodeFile(path);
                thumbnail = Bitmap.createScaledBitmap(thumbnail, 100, 100,
                        false);

                return thumbnail;
            } catch (Exception e) {

                return null;
            }
        }

        @Override
        protected void onPostExecute(Bitmap result) {
            // TODO Auto-generated method stub
            super.onPostExecute(result);

            if (holder != null && result != null) {

                Log.i("Ref", "Position = " + position + " " + holder);
                holder.img.setImageBitmap(result);
            } else {
                holder.img.setImageResource(R.drawable.format_picture);
            }
        }
    }
}

我也可以在启动asynktask之前通过注释行的帮助设置缩略图,但它会减慢我的列表通胀。

3 个答案:

答案 0 :(得分:2)

首先在类级别声明inflater,在getview中只写入条件,如果view为null,则创建并运行它。它肯定会奏效。

   LayoutInflater inflter = (LayoutInflater) LayoutInflater
                .from(context);
         ......
         ......

 public View getView(int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    if (convertView == null) {

      view = inflter.inflate(R.layout.list_layout_home, null);
   }

答案 1 :(得分:1)

滚动时,ListView会回收视图。您的问题正在发生,因为AsyncTask在视图被回收后完成,因此“旧”图像显示在回收的视图中。以下是解决问题的方法:

步骤1)更新您的获取视图,以便在开始AsyncTask之前加入一行

 holder.img.setTag(new Integer(position))
 new SetThumbnail().execute(new Thumbnail(holder, filePath, position));

步骤2)仅当位置与标记相同时才设置图片(更新您的onPostExecute):

@Override
protected void onPostExecute(Bitmap result) {
    if(holder == null) return;

    int viewPosition = (Integer) holder.img.getTag();
    if(position == viewPosition) {
        if(result != null) {
            holder.img.setImageBitmap(result);
        }
        else {
            holder.img.setImageResource(R.drawable.format_picture);
        }
    }
}

答案 2 :(得分:0)

正如我所怀疑的那样,您正在从互联网下载图像以在您的图像视图中进行设置。由于延迟加载,图像会改变或改变,这意味着您的imageViews会在下载图像之前创建,而当您滚动android时,会将所下载的图像设置为它找到的第一个图像视图。它找到的imageview可能是错误的,因为在适配器重用内存中的getview方法分配给对象,这种可重用性会导致图像混乱。

然而,this is a nice project to solve this problem,我也使用并解决了我的问题。

你可能想尝试一下。

希望这会有所帮助,快乐编码......:)