您的位置:首页 > 移动开发 > Android开发

Android ListView onScroll NullPointerException ListView滚动崩溃

2013-11-18 22:52 417 查看
当我们使用ListView,想获取第一个ListItem的高度和宽度的时候,我们需要监听ListView的滚动。从我所犯的错误说起。我有一个ListView,里面有很多数据,我想设置一个固定的头部,然后需要的是获取第一个ListItem的位置,想知道位置,当然先要获得这个view,因为是动态的,需要在onScroll中获取,所以变成这以下:

public class TestListView extends ListFragment implements AbsListView.OnScrollListener {

@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {

}

@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
//获取第一个可见的view
View firstView = view.getChildAt(firstVisibleItem);
Log.d("hehe", "firtsview height is:" + firstView.getHeight() + ",width is:" + firstView.getWidth());
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
getListView().setOnScrollListener(this);
}
}

别高兴太早,这个代码根本跑不起来,一运行就会崩溃抛出异常:NullPointerException ,没错,就是firstView抛出来的。按照逻辑,onScroll中的View就是ListView,firstVisibleItem就是可见的第一个item,所以怎么都看不出为什么取不到View。仔细翻看文档,OnScrollListener是这么解释的:

/**
* Callback method to be invoked when the list or grid has been scrolled. This will be
* called after the scroll has completed
* @param view The view whose scroll state is being reported
* @param firstVisibleItem the index of the first visible cell (ignore if
*        visibleItemCount == 0)
* @param visibleItemCount the number of visible cells
* @param totalItemCount the number of items in the list adaptor
*/
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount);

firstVisibleItem会忽略visibleitemcount是零的情况,因为刚开始初始化的时候,visibleitemCount还是为零的,所以view.getChildAt 获取到的就是null,说白了,view还是null,怎么去得到呢?所以像下面修改:

@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (visibleItemCount == 0) {
return;
}
//获取第一个可见的view
View firstView = view.getChildAt(firstVisibleItem);
Log.d("hehe", "firtsview height is:" + firstView.getHeight() + ",width is:" + firstView.getWidth());
}


恩,忽略掉当count还为0的情况,这时能运行起来了。

但是,别高兴太早,只要往下滑超过一屏之后,你还是会发现又崩溃了,还是同样的错误,NullPointerException,又是空指针异常。。。搞了一个晚上,我也崩溃了。。。

到最后通过不断调试,发现了一个秘密:onScroll方法中的参数view根本就只是可见的item,不可见的item已经被回收了。这先要理解ListView的机制,它是这样的:当移出屏幕外的item的view是会重新回收利用的,所以ListView中的实际的View只有可见的,不可见的完全被回收了,详情见这里:http://android.amberfog.com/?p=296

参数view所表示的ListView,并不是表示ListView中有item一样多的View,它只有当前可见的。所以,ListView中第一个就是0,而不是firstVisibleItem的值,代码改成如下就可以正常运行了:

@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (visibleItemCount == 0) {
return;
}
//获取第一个可见的view
View firstView = view.getChildAt(0);
Log.d("hehe", "firtsview height is:" + firstView.getHeight() + ",width is:" + firstView.getWidth());
}

PS:这就是纠结一个晚上所明白的,代价有点高啊!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ListView onScroll
相关文章推荐