【问题标题】:ListView Changing Items During ScrollListView 在滚动期间更改项目
【发布时间】:2013-11-03 11:06:15
【问题描述】:

我正在使用自定义 ArrayAdapter 来实现 ListFragment 以填充列表。每个行项都有一个 ImageView 和三个 TextView。正在通过 XML 解析数据,并且正在异步加载图像。

我遇到的问题是 ListView 填充并且看起来不错,但是滚动时出现问题。我可以一次在屏幕上放置 7 个项目。当我滚动到第 8 行时,它突然发生了变化,因此应该出现下一行。它仅在可被 8 整除的行上执行(即第 8、16、24 行等)。

我正在使用 ViewHolder 模式来确保此 ListView 具有良好的速度。我认为问题出在某个地方,但我已经四处搜索,看来我正在正确地执行此模式,并且为了解决此问题,我已经用完了要检查的东西。我究竟做错了什么?谢谢!

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View row = convertView;
    MyViewHolder holder;
    if (row == null) {
        LayoutInflater inflater = LayoutInflater.from(mContext);
        row = inflater.inflate(R.layout.browse_result_list_item, null, false);
        holder = new MyViewHolder();
        holder.adTitle = (TextView) row.findViewById(R.id.adTitle);
        holder.region = (TextView) row.findViewById(R.id.region);
        holder.time = (TextView) row.findViewById(R.id.time);
        holder.thumbnail = (ImageView) row.findViewById(R.id.browseThumbnail);
        row.setTag(holder);
    } else {
        holder = (MyViewHolder) row.getTag();
    }
    SearchResult result = mObjects.get(position);

    holder.adTitle.setText(result.getTitle().substring(0, result.getTitle().length()-3)); // three ... at the end, remove them
    holder.region.setText(result.getRegion());
    holder.time.setText(result.getPostingTime());

    // Download the image thumbnail
    ArrayList<String> urls = result.getImageUrls();
    if (urls.size() > 0)
        download(urls.get(0), holder.thumbnail);
    else // No image for this post, put a placeholder
        holder.thumbnail.setImageResource(R.drawable.ic_action_picture);

    return row;
}

private static class MyViewHolder {
    public static TextView adTitle;
    public static TextView region;
    public static TextView time;
    public static ImageView thumbnail;
}

编辑:感谢@frozenkoi,我找到了solution。最终成为 ViewHolder 中的静态变量导致问题。它们现在只是公共的,并且类是静态的,问题已经解决了。

【问题讨论】:

  • 您没有显示download 函数的代码。最有可能当您滚动时,您有两个异步下载更新相同的ImageView。您需要确保当ListView 回收一行视图时,它仅由正确的下载器更新,而不是由该视图之前表示的行的下载器更新。
  • 如果这句话读作“它突然变为应该出现的下一行。”反而?你能举一个效果的例子吗? 1 2 3 4 5 6 7 变成什么?
  • 更多关于在列表或网格视图中延迟加载图像的信息:stackoverflow.com/questions/541966/…
  • 如果对stackoverflow.com/questions/16789676/…有帮助,请勾选此项。延迟加载

标签: android listview scroll


【解决方案1】:

首先在getView()方法中定义成convertView=null; 并在此方法中注释 else 条件并添加int type = getItemViewType(position);。 还要从 ViewHolder 类中的每个 View 项中删除静态关键字,例如 Textview, ImageView

注意:覆盖你的 getViewTypeCount() 和 getItemViewType() 适配器。

if(convertView == null){
 switch (type) {
            case 0:
                  //First view[Row layout]
            break;
            case 1:
                 //Second view[Row layout]
            break;

            //another Case here....

   convertView.setTag(holder);

  //remove else part when used convertView =null;
        /*else {
        holder = (MyViewHolder) row.getTag();
    }*/

} 

@Override
    public int getItemViewType(int position) {
        // TODO Auto-generated method stub
        map = list.get(position); 
        message_type = map.get("message_type");
        if (message_type.equalsIgnoreCase("TEXT")) {
            return 0;
        } else {
            return 1;
        }

    }

    @Override
    public int getViewTypeCount() {
        // TODO Auto-generated method stub
        if (getCount() != 0)
            return getCount();
        return 2;
    }

现在就做! 完成!

【讨论】:

    【解决方案2】:

    感谢@frozenkoi,我找到了解决方案。最终成为 ViewHolder 中的静态变量导致问题。它们现在只是公共的,并且类是静态的,问题已经解决了。

    private static class MyViewHolder {
        public TextView adTitle;
        public TextView region;
        public TextView time;
        public ImageView thumbnail;
    }
    

    【讨论】:

    • 我收到The member type ViewHolder cannot be declared static; static types can only be declared in static or top level types
    【解决方案3】:

    只需在您的适配器类中添加这些代码行。

    @Override
    public int getViewTypeCount() {
    
        if (getCount() != 0)
            return getCount();
    
        return 1;
    }
    

    希望它能解决您的问题。

    【讨论】:

      【解决方案4】:

      只有在定义视图变量变量静态时才会出现问题。 否则,无论是否在滚动中使用 viewholder,listview 都可以正常工作。

      【讨论】:

      • 欢迎来到stackoverflow!除非您有具体的答案,否则尽量避免在答案中发表评论。请使用下面的评论框,一旦您有足够的声誉,您就可以对任何帖子发表评论。 :)
      【解决方案5】:

      在我的情况下 revert backif else 条件下被遗忘:

      /*public class ContactAdapter extends BaseAdapter {
          public List<Contact> _data;
          private ArrayList<Contact> arraylist;
          Context _c;
          ViewHolder holder;
      
      public ContactAdapter(List<Contact> contacts, Context context) {
          _data = contacts;
          _c = context;
          this.arraylist = new ArrayList<Contact>();
          this.arraylist.addAll(_data);
      }*/
      @Override
      public View getView(final int i,  View convertView, final ViewGroup viewGroup) {
          View view = convertView;
          final Contact data = (Contact) _data.get(i);
          ViewHolder holder ;
      
          if (view == null) {
              Context context = viewGroup.getContext();
              LayoutInflater inflater = LayoutInflater.from(context);
              view = inflater.inflate(R.layout.contact_list, null,false);
              holder = new ViewHolder();
              holder.title = (TextView) view.findViewById(R.id.name);
              holder.imageView = (ImageView) view.findViewById(R.id.pic);
              view.setTag(holder);
          } else {
              holder = (ViewHolder) view.getTag();
          }
      
          holder.title.setText(data.getName());
          // Set image if is null string
          if(!data.getThumb().equals("null")){
              try {
                   Bitmap myBitmap = BitmapFactory.decodeFile(ImageStorage.getImage(data.getThumb()).getAbsolutePath());
                   holder.imageView.setImageBitmap(myBitmap);
                  }catch (Exception e){e.printStackTrace();
                   holder.imageView.setImageResource(R.mipmap.contactimage);
                }
      
          }else // I had forgotten this else 
              holder.imageView.setImageResource(R.mipmap.contactimage); 
      
      
          // same action with background color
          if(data.getId()==data.getFromContact() ){
               view.setBackgroundColor(Color.RED);
           } else{
               view.setBackgroundColor(Color.WHITE); //**revert back it**
           }
              return view;
      }
      

      ViewHolder

        private  static class ViewHolder {
          ImageView imageView;
          TextView title;
      
      }
      

      【讨论】:

        猜你喜欢
        • 2015-11-10
        • 1970-01-01
        • 2017-04-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-28
        • 1970-01-01
        相关资源
        最近更新 更多