Android ListView通用图像加载器在滚动上更改图像

我有一个问题,现在已经让我悲伤了好几个星期了。 当我更新到新的Facebook SDK时,我忘记了一段时间,但现在它又回到了我的梦想中。

我基本上是在制作一个Facebook提要阅读器。 它从API调用中获取JSON数据并使用它填充ListView。 每次定制适配器调用getView()方法时,它都会检查它是什么类型的“状态”。 如果是“照片”状态,则该视图将具有两个图像(配置文件图片和状态更新图片)。 我使用nostra13的通用图像加载程序在使用持有人类扩充ImageViews来加载两个图像以帮助回收视图。 这就是我认为我的问题存在的地方。

当我滚动浏览列表时,所有的个人资料图片加载得很好,效果很好。 但是当我滚动时,状态照片会做一些事情:

1.)所有加载相同的图像(我以前没有这个问题,但我给自己试图修复其他问题)。

2.)图像四处跳动,或者消失,或者出现在不同的视图中,而不是它们应该显示的。

3.)如果图像正确加载,并不都显示相同的图像,图像会随着我上下滚动而改变,最终会全部成为相同的图像。

我会发布我的getView()代码(对不起,它很长)。

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

    final ViewHolder holder;

    try {
        jsonObject = getItem(position);
        jsonFrom = jsonObject.getJSONObject("from");
        postType = jsonObject.getString("type");
        posterName = jsonFrom.getString("name");
        posterID = jsonFrom.getString("id");
        posterPhoto = "http://graph.facebook.com/" + posterID
                + "/picture?type=square";
        if (jsonObject.has("message")) {
            posterMessage = jsonObject.getString("message");
        } else {
            posterMessage = jsonObject.getString("story");
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }

    if (postType.equals("status")) {
        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.status_post_holder,null);
            holder = new ViewHolder();
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.posterName = (TextView) convertView.findViewById(R.id.posterName);
        holder.posterMessage = (TextView) convertView.findViewById(R.id.posterMessage);
        holder.posterProfilePhoto = (ImageView) convertView.findViewById(R.id.posterProfilePic);

        if (jsonObject != null) {
            holder.posterName.setText(posterName);
            if (posterMessage != null) {
                holder.posterMessage.setText(posterMessage);
            } else {
                holder.posterMessage.setText("No message for this post.");
            }
            profileImageLoader.displayImage(posterPhoto,
                    holder.posterProfilePhoto);
        }

    }

    else if (postType.equals("photo")) {
        if (convertView == null) {
            try {
                posterImageURL = jsonObject.getString("picture");
            } catch (JSONException e) {
                e.printStackTrace();
            }
            LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.photo_post_holder, null);
            holder = new ViewHolder();
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.posterName = (TextView) convertView.findViewById(R.id.posterName);
        holder.posterMessage = (TextView) convertView.findViewById(R.id.posterMessage);
        holder.posterProfilePhoto = (ImageView) convertView.findViewById(R.id.posterProfilePic);
        holder.posterImage = (ImageView) convertView.findViewById(R.id.posterImage);

        if (jsonObject != null) {
            holder.posterName.setText(posterName);
            if (posterPhoto != null) {
                profileImageLoader.displayImage(posterPhoto,holder.posterProfilePhoto);
            }
            if (posterImageURL != null) {
                pictureImageLoader.displayImage(posterImageURL,holder.posterImage);
            }

            if (posterMessage != null) {
                holder.posterMessage.setText(posterMessage);
            } else {
                holder.posterMessage.setText("No message for this post.");
            }
        }

    }

    else if (postType.equals("link")) {
        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.status_post_holder,null);
            holder = new ViewHolder();
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.posterName = (TextView) convertView.findViewById(R.id.posterName);
        holder.posterMessage = (TextView) convertView.findViewById(R.id.posterMessage);
        holder.posterProfilePhoto = (ImageView) convertView.findViewById(R.id.posterProfilePic);

        if (jsonObject != null) {
            holder.posterName.setText(posterName);
            if (posterMessage != null) {
                holder.posterMessage.setText(posterMessage);
            } else {
                holder.posterMessage.setText("No message for this post.");
            }
            profileImageLoader.displayImage(posterPhoto,holder.posterProfilePhoto);
        }
    }

    else {
        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.status_post_holder,null);
            holder = new ViewHolder();
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.posterName = (TextView) convertView.findViewById(R.id.posterName);
        holder.posterMessage = (TextView) convertView.findViewById(R.id.posterMessage);
        holder.posterProfilePhoto = (ImageView) convertView.findViewById(R.id.posterProfilePic);

        if (jsonObject != null) {
            holder.posterName.setText(posterName);
            if (posterMessage != null) {
                holder.posterMessage.setText(postType);
            } else {
                holder.posterMessage.setText("No message for this post.");
            }
            profileImageLoader.displayImage(posterPhoto,holder.posterProfilePhoto);
        }
    }

    return convertView;

}

我确定它与Android回收视图有关并且效率很高,但是我无法弄清楚我在哪里做出错误。 奇怪的是,这个问题只存在于一个图像视图中。 任何帮助都会很热。 谢谢。

更新:我们发现这是我的JSON解析错误。 您必须使用setTag()来保留特定于该订单项的图片。 适配器试图将视图的标签设置为null,从而导致NPE。

再次更新:挖掘更多内容后,它看起来像是ImageView本身提供了空值,就好像它没有找到正确的布局。 我为不同类型的帖子使用了两种不同的xml布局。 所以现在看起来最好的解决方案是使用相同的布局,并根据状态类型在每个视图中有条件地膨胀不同的元素。


请在使用和处理图像加载器类时详细说明。 如果可能的话,不要创建同一个类的更多实例。 而不是以不同的方式使用相同的实例。

请参阅下面的适配器类,并尝试将其集成到您的案例中。 这将帮助你。

 private class OrderAdapter extends ArrayAdapter<User> {
        private ArrayList<User> items;
        Activity a;
        public ImageLoader imageLoader;

        public OrderAdapter(Context context, int textViewResourceId,ArrayList<User> items) {
            super(context, textViewResourceId, items);
            this.items = items;
            // extra
            /*if (Utility.model == null) {
                Utility.model = new FriendsGetProfilePics();
            }
            Utility.model.setListener(this);*/
        }

        /*@Override
        public boolean isEmpty() {
            // TODO Auto-generated method stub
            super.isEmpty();
            return false;
        }*/

        @Override
        public View getView(final int position, View convertView,ViewGroup parent) {
            ViewHolder holder;
            View v = convertView;
            if (v == null) {
                LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);

                v = vi.inflate(R.layout.add_buddies_row_new, null);
                holder = new ViewHolder();
                imageLoader = new ImageLoader(NotificationsActivity.this);
                //--------------

                //---------------------------------------------------------------------
                // for head to head
                holder.userName = (TextView) v.findViewById(R.id.txtName);
                holder.userPic = (ImageView) v.findViewById(R.id.imgUserPic);
                holder.userCity = (TextView) v.findViewById(R.id.txtCity);
                holder.userState = (TextView) v.findViewById(R.id.txtstate);
                holder.userCountry = (TextView) v.findViewById(R.id.txtContry);
                //---------------------------------------------------------------------

                v.setTag(holder);

            }else{
                holder=(ViewHolder)v.getTag();
            }

            final User o = items.get(position);
            holder = (ViewHolder) v.getTag();

            if (o != null) {
                holder.userName.setText(o.getUserName());
                holder.userCity.setText(o.getUserCity()+", ");
                holder.userState.setText(o.getUserState()+", ");
                holder.userCountry.setText(o.getUserCountry());
                System.out.println("PIC: "+o.getUserPic());
                holder.userPic.setTag(o.getUserPic());
                imageLoader.DisplayImage(o.getUserPic(), a, holder.userPic);
            }
            return v;
        }
    }

    class ViewHolder {
        TextView userName ;
        TextView userCity;
        TextView userState;
        TextView userCountry;
        ImageView userPic ;
    }

评论我的任何回报。

注意:您必须根据您的要求对上述代码进行一些更改。

如果你的问题没有解决这个问题,让我知道。

它也可能发生,如果你得到空数据,请确认获取数据。


我知道自创建主题以来已经有一段时间了,但是我为@Wenger的NPE提供的解决方案出现了,因为我在View成员(而不是ViewHolder)上使用了findViewById:

holder.userName = (TextView) v.findViewById(R.id.txtName);

工作参考:

holder.userName = (TextView) convertView.findViewById(R.id.txtName);

我有与查看持有人模式和通用图像加载器相同的问题。

我之前我打电话通用加载器显示图像检查我的网址,如果URL为空,我不下载图像只是设置ImageView背景可绘制我的图像无法绘制。 在列表视图滚动我的列表视图图像混合。

然后,我试图不检查网址,如果它为空,只是设置一个无链接可绘制通用图像加载器显示图像选项。 这解决了我的问题。 我不知道这是否是此问题的通用解决方案,但您可以尝试。

链接地址: http://www.djcxy.com/p/11535.html

上一篇: Android ListView Universal Image Loader Changes Images on Scroll

下一篇: Express general monadic interface (like Monad class) in C++