实际开发过程当中,我遇到了这样的问题,listview一个item里面有一个大的banner图,banner图上又盖了个10%透明度的蒙层(为了如果banner图是白色的那种,让标题的字显示出来),还盖了各种各样的图(要根据类别判断显示或隐藏),底下还有很多标题,按钮,还包括两个自定义的viewgroup(在adapter里面不断的往布局里填充或者移除控件),等等等等。。。。
相信这种需求在Android开发中还是很常见的,列表的优化问题就很重要了。
当然adapter要用viewholder来写,充分利用listview的缓存机制,然后在getView()方法里写咯,在getView里尽量采用异步处理咯,但是这往往还是不够的。Android机器实在太多了,性能上的差异性也有很大的区别,所以在有些机器上,卡顿现象还是会存在的。
那应该怎么办呢?其实大家都知道,getView()方法里面不能执行耗时操作,就比如加载图片什么的,必须采用异步来解决,imageLoader就是个很好的方法。但是因为异步的东西多了,就会出现这么一个情况,如果用户刻意地频繁地上下滑动,就会在一瞬间产生大量的异步任务,这么多的异步任务就会造成线程池的拥堵以及带来大量的UI更新的操作,而这些UI更新的操作都是在主线程上操作的,所以就会出现一定程度的卡顿现象了。
所以,要解决这个问题,可以考虑在列表滑动的时候不去做那些异步任务,等列表停下来的时候再去操作这些异步任务,这样子操作的话仍然可以获得良好的用户体验。
具体代码操作我就举一个简单的例子,Adapter里是这样的,为了简化操作,item里面只有一个textView的,在这里假设textView的setText()就是个异步处理,adapter的代码如下:
public class ListAdapter extends BaseAdapter{
private List<String> stringList;
private Context context;
private LayoutInflater layoutInflater;
private ListView listView;
private boolean isListViewIdle = true;
public ListAdapter(List<String> stringList,Context context,ListView listView){
this.context = context;
layoutInflater = LayoutInflater.from(context);
this.stringList = stringList;
this.listView = listView;
this.listView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView absListView, int scrollState) {
isListViewIdle = true;
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE){
updateUI();
}else {
isListViewIdle = false;
}
}
@Override
public void onScroll(AbsListView absListView, int i, int i1, int i2) {
}
});
}
private void updateUI() {
this.notifyDataSetChanged();
}
@Override
public int getCount() {
return stringList.size();
}
@Override
public Object getItem(int i) {
return stringList.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder = null;
if (viewHolder == null){
view = layoutInflater.inflate(R.layout.item,viewGroup,false);
viewHolder = new ViewHolder();
viewHolder.textView = (TextView)view.findViewById(R.id.text);
view.setTag(viewHolder);
}else {
viewHolder = (ViewHolder)view.getTag();
}
if (isListViewIdle){
viewHolder.textView.setText(stringList.get(i));
}else {
viewHolder.textView.setText("加载中………");
}
return view;
}
class ViewHolder{
TextView textView;
}
}
在adapter里我把listview传递了进来,让listview实现onScollListener,在onScrollListener里面监听listView的滑动现在是静止的还是在滑动的,滑动的话,就给textView设置“加载中”(就是显示默认的东西,这里同样做了简化),静止的时候 加载数据。在Activity就是简单的listView.setAdapter.........
但是以上操作我在pulltorefreshListView里也进行了试验,却没有达到想要的效果,设置了onScrollListener以后,就无法上拉加载,产生冲突了,这个问题,我还得看一下,看看有没有好的解决的办法。
这样子操作,正常的ListView和GridView,如果一个item里面有很多异步任务的时候性能上就得到了提升。在网上找资料的时候,我还发现了这个,在某些特殊情况下,列表还是会有偶尔的卡顿现象,这个时候还可以开启硬件加速。绝大多数情况下,硬件加速都可以解决莫名的卡顿问题,通过设置android:hardwareAccelerated=“true”即可为Activity开启硬件加速。
以上方法就是我对这个问题所想到的优化的方法,如果各位大神还有其他更好的方法的,留言给我下思路吧!!!谢谢!!!