ListView如何优化

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ListView如何优化相关的知识,希望对你有一定的参考价值。

1、ListView 如何提高其效率?

    当 convertView 为空时,用 setTag()方法为每个 View 绑定一个存放控件的ViewHolder 对象。 当 convertView 不为空, 重复利用已经创建的 view 的时候,

使用 getTag()方法获取绑定的 ViewHolder 对象,这样就避免了 findViewById,

对控件的层层查询,而是快速定位到控件。

       ① 复用 ConvertView,使用历史的 view,提升效率 200%
       ② 自定义静态类 ViewHolder,减少 findViewById 的次数。提
           升效率 50%
       ③ 异步加载数据,分页加载数据。
       ④ 使用 WeakRefrence 引用 ImageView 对象


2、当 ListView 数据集改变后,如何更新 ListView?

  使用该 ListView 的 adapter 的 notifyDataSetChanged()方法,该方法会使 ListView 重新绘制。

 

3、ListView 如何实现分页加载

  ① 设 置 ListView 的 滚 动 监 听 器 : setOnScrollListener(new OnScrollListener{….})

        在 监 听 器 中 有 两 个 方 法 : 滚 动 状 态 发 生 变 化 的 方 法(onScrollStateChanged)和 listView 被滚动时调用的方法(onScroll),

  ② 在滚动状态发生改变的方法中,有三种状态:

    手指按下移动的状态: SCROLL_STATE_TOUCH_SCROLL: // 触摸滑动

    惯性滚动(滑翔(flgin)状态): SCROLL_STATE_FLING: // 滑翔
    静止状态: SCROLL_STATE_IDLE: // 静止
  对不同的状态进行处理:
    分批加载数据,只关心静止状态:关心最后一个可见的条目,如果最后一个可见条目就是数据适配器(集合)里的最后一个,此时可加载更多的数据。在每
    次加载的时候,计算出滚动的数量,当滚动的数量大于等于总数量的时候,可以提示用户无更多数据了。

4、ListView 可以显示多种类型的条目吗?

  这个当然可以的,ListView 显示的每个条目都是通过 baseAdapter 的getView(int position, View convertView, ViewGroup parent)来展示的,理论
  上我们完全可以让每个条目都是不同类型的 view。    除 此 之 外 adapter 还 提 供 了 getViewTypeCount ( ) 和getItemViewType(int position)两个方法。

  在 getView 方法中我们可以根据不同的 viewtype 加载不同的布局文件


5、ListView 如何定位到指定位置?
  可以通过 ListView 提供的 lv.setSelection(listView.getPosition());方法。

 

6、如何在 ScrollView 中如何嵌入 ListView?

  通常情况下我们不会在 ScrollView 中嵌套 ListView,但是如果面试官非让我们嵌套的话也是可以的。

  在 ScrollView 添加一个 ListView 会导致 listview 控件显示不全,通常只会显示一条,这是因为两个控件的滚动事件冲突导致。 所以需要通过 listview 中的
  item 数量去计算 listview 的显示高度,从而使其完整展示,如下提供一个方法供大家参考。
    
    

  lv = (ListView) findViewById(R.id.lv);
  adapter = new MyAdapter();
  lv.setAdapter(adapter);
  setListViewHeightBasedOnChildren(lv);
----------------------------------------------------
  public void setListViewHeightBasedOnChildren(ListView listView) {
  ListAdapter listAdapter = listView.getAdapter();
  if (listAdapter == null) {
  return;
  }
  int totalHeight = 0;
  for (int i = 0; i < listAdapter.getCount(); i++) {
  View listItem = listAdapter.getView(i, null, listView);
  listItem.measure(0, 0);
  totalHeight += listItem.getMeasuredHeight();

  }


  ViewGroup.LayoutParams params = listView.getLayoutParams();
  params.height = totalHeight + (listView.getDividerHeight() *
  (listAdapter.getCount() - 1));
  params.height += 5;

  // if without this statement,the listview will be a
  // little short
  listView.setLayoutParams(params);
  }

 

  现阶段最好的处理的方式是: 自定义 ListView,重载 onMeasure()方法,设置全部显示。代码如下:

  package com.meiya.ui;
  import android.widget.ListView;
  public class ScrollViewWithListView extends ListView {
  public ScrollViewWithListView(android.content.Context context,
  android.util.AttributeSet attrs) {
  super(context, attrs);
  }
  /**
  * Integer.MAX_VALUE >> 2,如果不设置,系统默认设置是显示两条
  */
  public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
  MeasureSpec.AT_MOST);
  super.onMeasure(widthMeasureSpec, expandSpec);
  }
  }



7、ListView 中如何优化图片

  图片的优化策略比较多。

  1、处理图片的方式:
  如果 ListView 中自定义的 Item 中有涉及到大量图片的, 一定要对图片进行细心的处理,因为图片占的内存是 ListView 项中最头疼的,处理图片的方法

  大致有以下几种:
    ①、不要直接拿路径就去循环 BitmapFactory.decodeFile;使用 Options 保存图片大小、不要加载图片到内存去。
    ②、对图片一定要经过边界压缩尤其是比较大的图片,如果你的图片是后台服务器处理好的那就不需要了
    ③、在 ListView 中取图片时也不要直接拿个路径去取图片,而是以WeakReference ( 使 用 WeakReference 代 替 强 引 用 。 比 如 可 以 使 用
      WeakReference mContextRef)、SoftReference、WeakHashMap 等的来存储图片信息。
    ④、在 getView 中做图片转换时,产生的中间变量一定及时释放
  2、异步加载图片基本思想:
    1)、 先从内存缓存中获取图片显示(内存缓冲)
    2)、获取不到的话从 SD 卡里获取(SD 卡缓冲)
    3)、都获取不到的话从网络下载图片并保存到 SD 卡同时加入内存并显示
    (视情况看是否要显示)
  原理:
    优化一:先从内存中加载,没有则开启线程从 SD 卡或网络中获取,这里注意从 SD 卡获取图片是放在子线程里执行的,否则快速滑屏的话会不够流畅。
      
    优化二:于此同时,在 adapter 里有个 busy 变量,表示 listview 是否处于滑动状态,如果是滑动状态则仅从内存中获取图片,没有的话无需再开启线程去
        外存或网络获取图片。
    优化三:ImageLoader 里的线程使用了线程池,从而避免了过多线程频繁创建和销毁,如果每次总是 new 一个线程去执行这是非常不可取的,好一点的
        用的 AsyncTask 类,其实内部也是用到了线程池。在从网络获取图片时,先是将其保存到 sd 卡,然后再加载到内存,这么做的好处是在加载到

           内存时可以做个压缩处理,以减少图片所占内存。
      
 8、ListView 中图片错位的问题是如何产生的

  图片错位问题的本质源于我们的 listview 使用了缓存 convertView, 假设一种场景,一个 listview 一屏显示九个 item,那么在拉出第十个 item 的时候,
  事实上该 item 是重复使用了第一个 item,也就是说在第一个 item 从网络中下载图片并最终要显示的时候,其实该 item 已经不在当前显示区域内了,此时显示
  的后果将可能在第十个 item 上输出图像,这就导致了图片错位的问题。所以解决之道在于可见则显示,不可见则不显示。
  

9、如何刷新 ListView 中单个 item 的数据,不刷新整个ListView 的数据?

  修改单个 Item 的数据,然后调用适配器的 notifyDataSetChanged()方法

  

 

以上是关于ListView如何优化的主要内容,如果未能解决你的问题,请参考以下文章

Android小白的成长之路-ListView优化提案

基于Android官方AsyncListUtil优化经典ListView分页加载机制

Android ListView 全面优化

谈谈-ListView的优化

android-----带你一步一步优化ListView

ListView的优化总结