【问题标题】:Make ListView Scroll Smoothly使 ListView 平滑滚动
【发布时间】:2018-12-30 10:38:54
【问题描述】:

我有以下代码来加载我的 ListView(每个项目都有一个图像和文本):

public View getView(final int i, View convertView, ViewGroup viewGroup) {
    View view = inflater.inflate(R.layout.contact_inflater, null);
    final Holder holder = new ContactAdapter.Holder();

    holder.ivPhoto = (ImageView) view.findViewById(R.id.ivImage);
    holder.tvFullName = (TextView) view.findViewById(R.id.tvName);
    holder.tvPhoneNumber = (TextView) view.findViewById(R.id.tvPhoneNo);
    holder.tvFullName.setText(Contact.get(i).get(0));
    holder.tvPhoneNumber.setText(Contact.get(i).get(1));
    holder.button = (Button) view.findViewById(R.id.ivButton);
        
    Picasso.with(context)
                .load(Contact.get(i).get(2))
                .into(holder.ivPhoto);
    
    return view;
}

问题是列表滚动不顺畅。如何让它顺利?

编辑:我已更改为 RecycleView,但忘记添加以下代码:

if(//IF//){ 
    Log.d("InInIn!", "InInIn!"); 
    
    //Turn to Tagged
}

当我把它变成一个 RecycleView 时,按钮会在整个过程中变成 Tagged,并且被标记的按钮会随着滚动而变化。按钮在各处都在变化,即使它们不应该发生变化。有什么问题?

【问题讨论】:

  • AFAIK,毕加索将异步加载图像。这里滚动的问题不是毕加索。这是您的 getView 实现中缺少viewholder pattern
  • 如何修复我的视图模式?
  • 改用 RecyclerView
  • 我是初学者,如何改成recyclerView?
  • 您不需要使用 RecyclerView,但至少需要更改 ViewHolder 代码。 ViewHolder 的重点是不必每次都调用findViewById(参见developer.android.com/training/improving-layouts/…javacodegeeks.com/2013/09/…)。不过,毕加索的负载也可能是一个问题。您应该对其进行分析以查看慢的原因。

标签: android list listview android-asynctask


【解决方案1】:

您应该改用recyclerView。它是 ListView 的更高级和灵活的版本。请通过https://developer.android.com/guide/topics/ui/layout/recyclerview 获取指导。

如果您想坚持使用 ListView,那么为了提高性能,您应该回收/重用用户不再可见的视图。

public View getView(final int i, View convertView, ViewGroup viewGroup) {
       
    Holder holder = null;
    if(convertView == null){
        convertView = inflater.inflate(R.layout.contact_inflater, null);
        final Holder holder = new ContactAdapter.Holder();
        holder.ivPhoto = (ImageView) convertView.findViewById(R.id.ivImage);
        holder.tvFullName = (TextView) convertView.findViewById(R.id.tvName);
        holder.tvPhoneNumber = (TextView) convertView.findViewById(R.id.tvPhoneNo);
        holder.button = (Button) convertView.findViewById(R.id.ivButton);
        convertView.setTag(holder)
    }
    else{
        holder = (Holder)convertView.getTag()
    } 

    holder.tvFullName.setText(Contact.get(i).get(0));
    holder.tvPhoneNumber.setText(Contact.get(i).get(1));

    Picasso.with(context)
                .load(Contact.get(i).get(2))
                .into(holder.ivPhoto);

    return convertView;
}

【讨论】:

  • 这有助于解决一个问题。
  • 有什么问题?
  • 我将编辑代码,但如果电话号码等于某个值,则更改按钮。如果我在上面这样做,即使它不应该,按钮也会在整个地方发生变化。
  • 我遇到了你的问题,试试这个:holder.tvFullName.setText(Contact.get(i).get(0)); holder.tvPhoneNumber.setText(Contact.get(i).get(1));在此之后添加您的 if-else 以更改按钮。
  • 有什么区别?
【解决方案2】:

您可以调试并检查接收到 Picasso 的内容,添加:un listener for watch the error

        .into(ontact.get(i).get(2), new Callback() {
            @Override
            public void onSuccess() {
            }

            @Override
            public void onError(Exception e) {
            }
        })

【讨论】:

  • 毕加索不是问题?
  • 你检查文档并在调试器中显示错误,如果接收数据时不显示代码我不知道是什么问题
【解决方案3】:

您必须在列表适配器中使用数据绑定并获取布局组件,而无需在 getView 方法中使用 findViewById。

【讨论】:

    【解决方案4】:
    public View getView(final int i, View convertView, ViewGroup viewGroup) {
        Holder holder;
        if(null == convertView){
            holder = new ContactAdapter.Holder();
            convertView = inflater.inflate(R.layout.contact_inflater, null);
            holder.ivPhoto = (ImageView) view.findViewById(R.id.ivImage);
            holder.tvFullName = (TextView) view.findViewById(R.id.tvName);
            holder.tvPhoneNumber = (TextView) view.findViewById(R.id.tvPhoneNo);
            holder.button = (Button) view.findViewById(R.id.ivButton);
            converView.setTag(holder);
        }else{
            holder = (Holder) convertView.getTag();
        }
        holder.tvFullName.setText(Contact.get(i).get(0));
        holder.tvPhoneNumber.setText(get(i).get(1));
        Picasso.with(context)
                        .load(Contact.get(i).get(2))
                        .into(holder.ivPhoto);
        return view;
    }
    

    【讨论】:

      【解决方案5】:

      试试这个:

      这是新的和更新的 getView 滚动速度更快

      @Override
      public View getView(int position, View convertView, ViewGroup paramViewGroup) {
          Object current_event = mObjects.get(position);
          ViewHolder holder = null;
      
          if (convertView == null) {
              holder = new ViewHolder();
              convertView = inflater.inflate(R.layout.row_event, null);
              holder.ThreeDimension = (ImageView) convertView.findViewById(R.id.ThreeDim);
              holder.EventPoster = (ImageView) convertView.findViewById(R.id.EventPoster);
              // This will now execute only for the first time of each row
              RelativeLayout.LayoutParams imageParams = new RelativeLayout.LayoutParams(measuredwidth, rowHeight);
              holder.EventPoster.setLayoutParams(imageParams);
              convertView.setTag(holder);
          } else {
              holder = (ViewHolder) convertView.getTag();
          }
      
          // This way you can simply avoid conditions
          holder.ThreeDimension.setVisibility(object.getVisibility());
      
          return convertView;
      }
      

      【讨论】:

        猜你喜欢
        • 2017-03-12
        • 2014-01-12
        • 1970-01-01
        • 2016-05-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-01
        • 2011-10-19
        相关资源
        最近更新 更多