Android ListView onScroll NullPointerException ListView滚动崩溃
2013-11-18 22:52
417 查看
当我们使用ListView,想获取第一个ListItem的高度和宽度的时候,我们需要监听ListView的滚动。从我所犯的错误说起。我有一个ListView,里面有很多数据,我想设置一个固定的头部,然后需要的是获取第一个ListItem的位置,想知道位置,当然先要获得这个view,因为是动态的,需要在onScroll中获取,所以变成这以下:
别高兴太早,这个代码根本跑不起来,一运行就会崩溃抛出异常:NullPointerException ,没错,就是firstView抛出来的。按照逻辑,onScroll中的View就是ListView,firstVisibleItem就是可见的第一个item,所以怎么都看不出为什么取不到View。仔细翻看文档,OnScrollListener是这么解释的:
firstVisibleItem会忽略visibleitemcount是零的情况,因为刚开始初始化的时候,visibleitemCount还是为零的,所以view.getChildAt 获取到的就是null,说白了,view还是null,怎么去得到呢?所以像下面修改:
恩,忽略掉当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的值,代码改成如下就可以正常运行了:
PS:这就是纠结一个晚上所明白的,代价有点高啊!
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:这就是纠结一个晚上所明白的,代价有点高啊!
相关文章推荐
- [置顶] 【Android】AndroidStudio空指针解决之:listview与adapter的使用报空 java.lang.NullPointerException
- 【Android】AndroidStudio空指针解决之:listview与adapter的使用报空 java.lang.NullPointerException
- NullPointerException at android.widget.AbsListView.obtainView at android.widget.GridView.onMeasure
- NullPointerException at android.widget.AbsListView.obtainView at android.widget.ListView.makeAndAddView
- NullPointerException at android.widget.AbsListView.obtainView at android.widget.GridView.onMeasure
- NullPointerException at android.widget.AbsListView.obtainView.
- Android Listview addHeaderView setadapter的时候莫名NullPointerException 解决
- Android Smack UserSearchManager (java.lang.ClassCastException java.lang.NullPointerException)
- Android: how to resolve Application’s parameter NullPointerException
- Android 2.3下重写PopupWindow的NullPointerException问题
- Android FragmentManager BackStackRecord.run throwing NullPointerException
- Android 中读取SD卡文件时抛出NullPointerException错误解决办法
- Android兼容性问题 -- RelativeLayout.mesure()出现NullPointerException异常
- Android - listview未滚动触发onScroll
- NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.la
- Android中利用NetworkInfo判断网络状态时出现空指针(NullPointerException)问题的解决方法
- Android布局文件使用<include>标签出现NullPointerException问题
- android 2.3 popwindow NullPointerException的解决
- android( java) 处理 null 和 预防空指针异常(NullPointerException) 的一些经验。
- 解决java.lang.NullPointerException Attempt to read from field 'int android.view.View.mViewFlags' on a