zoukankan      html  css  js  c++  java
  • ListView性能优化

    ListView在ScrollView中无法正确计算它的大小, 故不能显示正常的条目。

    解决办法有:

    1.重写ListView, 覆盖onMeasure()方法。

     1 public class WrapperListView extends ListView {
     2     public WrapperListView(Context context) {
     3         super(context);
     4     }
     5     public WrapperListView(Context context, AttributeSet attrs) {
     6         super(context, attrs);
     7     }
     8     public WrapperListView(Context context, AttributeSet attrs, int defStyleAttr) {
     9         super(context, attrs, defStyleAttr);
    10     }
    11     public WrapperListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    12         super(context, attrs, defStyleAttr, defStyleRes);
    13     }
    14     /**
    15      * 重写该方法,达到使ListView适应ScrollView的效果
    16      */
    17     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    18         int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
    19         super.onMeasure(widthMeasureSpec, expandSpec);
    20     }
    21 }

    2.动态设置LIstView的高度,不需要重写LIstView

    只需要在setAdapter之后调用如下方法即可:

    public void setListViewHeightBasedOnChildren(ListView listView) {
            // 获取ListView对应的Adapter
            ListAdapter listAdapter = listView.getAdapter();
            if (listAdapter == null) {
                return;
            }
            int totalHeight = 0;
            for (int i = 0, len = listAdapter.getCount(); i < len; i++) {
                // listAdapter.getCount()返回数据项的数目
                View listItem = listAdapter.getView(i, null, listView);
                // 计算子项View 的宽高
                listItem.measure(0, 0);
                // 统计所有子项的总高度
                totalHeight += listItem.getMeasuredHeight();
            }
            ViewGroup.LayoutParams params = listView.getLayoutParams();
            params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
            // listView.getDividerHeight()获取子项间分隔符占用的高度
            // params.height最后得到整个ListView完整显示需要的高度
            listView.setLayoutParams(params);
        }

    另外,这时,这时最好给ListView之外嵌套一层LinearLayout,不然有时候这种方法会失效。

    最后,尽量避免ScrollView嵌套Listview,可使用使用listview的addHeader() 函数来实现预期效果或者利用布局的特性达到预期效果。

    ListView就是一个将数据集合以动态滚动的方式展示到用户界面的View

    ListView的父类AbsListView中的内部类RecycleBin(防止ListView出现oom)

    优化:

    1. getview中的convertView中起到缓存作用,复用convertView,对convertView进行判空,为空则初始化,从而减少了很多不必要的View的创建、减少findViewById的次数

    2.采用ViewHolder模式缓存item条目的引用,减少多次findViewByID的次数

    3.避免在getView方法中做耗时操作

    3.给listView设置滚动监听器 根据不同状态 不同处理数据 分批分页加载 根据listView的状态去操作,比如当列表快速滑动时不去开启大量的异步任务去请求图片

    4.listview每个item层级结构不要太复杂
    5.listview每个item中异步加载图片,并对图片加载做优化,(关于Listview分页加载和图片异步加载思路请看接下来的文章内容)
    6.尽量能保证 Adapter 的 hasStableIds() 返回 true 这样在 notifyDataSetChanged() 的时候,如果item内容并没有变化,ListView 将不会重新绘制这个 View,达到优化的目的
    7.在一些场景中,ScollView内会包含多个ListView,可以把listview的高度写死固定下来。 由于ScollView在快速滑动过程中需要大量计算每一个listview的高度,阻塞了UI线程导致卡顿现象出现,如果我们每一个item的高度都是均匀的,可以通过计算把listview的高度确定下来,避免卡顿现象出现。
    8.使用 RecycleView 代替listview: 每个item内容的变动,listview都需要去调用notifyDataSetChanged来更新全部的item,太浪费性能了。RecycleView可以实现当个item的局部刷新,并且引入了增加和删除的动态效果,在性能上和定制上都有很大的改善
    9.ListView 中元素避免半透明: 半透明绘制需要大量乘法计算,在滑动时不停重绘会造成大量的计算,在比较差的机子上会比较卡。 在设计上能不半透明就不不半透明。实在要弄就把在滑动的时候把半透明设置成不透明,滑动完再重新设置成半透明。
    Listview的一些相关拓展
    1. 打开套有 ListVew的 ScrollView的页面布局默认起始位置不是最顶部
    解决办法有两种:
    方法一:把套在里面的ListVew 不让获取焦点即可。listview.setFocusable(false);注意:在xml布局里面设置android:focusable=“false”不生效
    方法二:myScrollView.smoothScrollTo(0,0);
     
    2.上拉加载和下拉刷新怎么实现

    1.继承自LIstView实现OnScrollListener
    实现OnScrollListener 接口重写onScrollStateChanged 和onScroll方法,
    使用onscroll方法实现”滑动“后处理检查是否还有新的记录,如果有,调用 addFooterView,添加记录到adapter, adapter调notifyDataSetChanged 更新数据;如果没有记录了,把自定义的mFooterView去掉。使用onScrollStateChanged可以检测是否滚到最后一行且停止滚动然后执行加载

    2.头部和尾部都是单独的两个继承自LinearLayout布局,通过LIstView的addHeaderView()和addFooterView()两个方法把其加载到LIstView中
    3.必须实现3个构造方法,每个方法都要实现initView()
    4.Visibility实现头部和底部布局显示与隐藏

    3.Listview里有Button就点不动了你知道吗

    当ListView的Item中包含button,item点击事件与Button控件(button换成TextView不会冲突)点击冲突解决办法
    1.不再对item进行监听,而是在adapter中监听整个item布局convertView.setOnClickListener()实现item的点击事件
    2.在item的布局文件中给button设置属性android:focusable="false"以防button抢占listview的点击

    4.ListView图片异步加载实现思路

    1.先从内存缓存中获取图片显示(内存缓冲)
    2.获取不到的话从SD卡里获取(SD卡缓冲,,从SD卡获取图片是放在子线程里执行的,否则快速滑屏的话会不够流畅)
    3.都获取不到的话从网络下载图片并保存到SD卡同时加入内存并显示(视情况看是否要显示)

    5.ViewHolder内部类非得要声明成static

    这不是Android的优化,而是Java提倡的优化,
    如果声明成员类不要求访问外围实例,就要始终把static修饰符放在它的声明中,使它成为静态成员类,而不是非静态成员类。
    因为非静态成员类的实例会包含一个额外的指向外围对象的引用,保存这份引用要消耗时间和空间,并且导致外围类实例符合垃圾回收时仍然被保留。如果没有外围实例的情况下,也需要分配实例,就不能使用非静态成员类,因为非静态成员类的实例必须要有一个外围实例。

  • 相关阅读:
    ubuntu docker 安装
    后缀数组小结
    后缀数组小结
    后缀数组小结
    win7下如何建立ftp服务器
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/evolutionoflicorice/p/10219678.html
Copyright © 2011-2022 走看看