基础知识:五、 ListView

五、 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,
ViewconvertView,ViewGroupparent)来展示的,理论上我们完全可以让每个条目都是不同类型的
view。
比如:从服务器拿回一个标识为id=1,那么当id=1的时候,我们就加载类型一的条目,当id=2
的时候,加载类型二的条目。常见布局在资讯类客户端中可以经常看到。
除此之外adapter还提供了getViewTypeCount()和getItemViewType(intposition)两个方
法。在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;
/** * * @Description: scrollview 中内嵌 listview 的简单实现 * * @File: ScrollViewWithListView.java * * * @Version */ 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()方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值