【问题标题】:How to load the Listview "smoothly" in android如何在android中“顺利”加载Listview
【发布时间】:2010-11-22 04:07:26
【问题描述】:

我将数据从光标加载到列表视图,但我的列表视图并没有真正显示“流畅”。当我在 ListView 的 scollbar 上上下拖动时,数据会发生变化。有些项目看起来像在我的列表中重复显示。 我有一个“复杂的 ListView”(两个 textview,一个 imageview)所以我使用 newView()、bindView() 来显示数据。有人可以帮我吗?

【问题讨论】:

    标签: android listview


    【解决方案1】:

    我将向您描述如何解决您遇到的此类问题。这可能会对您有所帮助。

    所以,在列表适配器中你有这样的代码:

    public View getView(int position, View contentView, ViewGroup arg2)
        {
            ViewHolder holder;
    
            if (contentView == null) {
                holder = new ViewHolder();
                contentView = inflater.inflate(R.layout.my_magic_list,null);
                holder.label = (TextView) contentView.findViewById(R.id.label);
                contentView.setTag(holder);
            } else {
                holder = (ViewHolder) contentView.getTag();
            }
    
            holder.label.setText(getLabel());
    
            return contentView;
        }
    

    如您所见,我们仅在检索到 holder 后才设置列表项值。

    但是如果你把代码移到上面的 if 语句中:

    holder.label.setText(getLabel());
    

    所以它会如下所示:

    if (contentView == null) {
       holder = new ViewHolder();
       contentView = inflater.inflate(R.layout.my_magic_list,null);
       holder.label = (TextView) contentView.findViewById(R.id.label);
       holder.label.setText(getLabel());
       contentView.setTag(holder);
    }
    

    您将拥有当前的应用程序行为与列表项重复。

    可能会有帮助。

    【讨论】:

      【解决方案2】:

      ListView 是个狡猾的野兽。

      首先您的第二个问题:您看到重复项是因为 ListView 通过 convertView 重复使用视图,但您不能确保重置转换后视图的所有方面。确保convertView!=null 的代码路径正确设置了视图的所有数据,并且一切都应该正常工作。

      如果您使用自定义视图,您会希望您的 getView() 方法大致如下所示:

      @Override
      public View getView(int position, View convertView, ViewGroup parent) {
          final MyCustomView v = convertView!=null ? (MyCustomView)convertView : new MyCustomView();
          v.setMyData( listAdapter.get(position) );
          return v;
      }
      

      如果您不使用自己的自定义视图,只需将调用 new MyCustomView() 替换为调用 inflater.inflate(R.layout.my_layout,null)

      关于您的第一个问题,您可以在这里观看 Romain 关于 ListView 性能的技术演讲:http://code.google.com/events/io/sessions/TurboChargeUiAndroidFast.html

      从他的谈话中,并根据我自己的经验按重要性排序,

      • 使用 convertView
      • 如果您有图像,请不要随意缩放图像。使用 Bitmap.createScaledBitmap 创建缩放位图并将其放入您的视图中
      • 使用 ViewHolder,这样您就不必每次都调用一堆 findViewByIds()
      • 降低列表视图中视图的复杂性。子视图越少越好。在这方面,RelativeLayout 比 LinearLayout 好得多。如果您要实现自定义视图,请务必使用。

      【讨论】:

      • 对不起,我用newView(),bindView()来显示数据。是不是同样的问题?
      • 我觉得我在视频中找到了一些有用的东西,谢谢分享!
      【解决方案3】:

      我也遇到了这个问题,但就我而言,我使用线程来获取外部图像。重要的是当前执行的线程不要改变imageView,如果它被重用了!

      public View getView(int position, View vi, ViewGroup parent) {
      ViewHolder holder;
      String imageUrl = ...;
      
      if (vi == null) {
          vi = inflater.inflate(R.layout.tweet, null);
          holder = new ViewHolder();
          holder.image = (ImageView) vi.findViewById(R.id.row_img);
          ...
          vi.setTag(holder);
      } else {
          holder = (ViewHolder) vi.getTag();      
      }
      holder.image.setTag(imageUrl);
      ...
      DRAW_MANAGER.fetchDrawableOnThread(imageUrl, holder.image);
      }
      

      然后在获取线程上,我正在执行重要检查

      final Handler handler = new Handler() {
      @Override
      public void handleMessage(Message message) {
           // VERY IMPORTANT CHECK
          if (urlString.equals(url))
              imageView.setImageDrawable((Drawable) message.obj);
      };
      
      Thread thread = new Thread() {  
      
      @Override
      public void run() {
          Drawable drawable = fetchDrawable(urlString);
          if (drawable != null) {
              Message message = handler.obtainMessage(1, drawable);
              handler.sendMessage(message);
          }
      }};
      thread.start();
      

      如果他们的视图被重用,也可以取消当前线程(就像 here 所描述的那样),但我决定不这样做,因为我想填充我的缓存以供以后重用。

      【讨论】:

        【解决方案4】:

        只有一个提示:切勿使用项目布局的透明背景 - 它会大大降低性能

        【讨论】:

          【解决方案5】:

          如果您以错误的方式处理它,您可以在多行中看到重复出现的文本。我最近写了一些关于它的博客 - 请参阅here。除此之外,您可能想看看ListView performance optimization。通常是因为视图重用,我已经看过几次了。

          【讨论】:

            猜你喜欢
            • 2018-05-18
            • 1970-01-01
            • 2015-10-10
            • 2012-10-26
            • 1970-01-01
            • 2020-04-06
            • 2014-03-18
            • 1970-01-01
            • 2010-10-07
            相关资源
            最近更新 更多