listview优化之分页
To live is to function,that is all there is in living.
当我们有大量的 数据需要展示的时候,但是这个时候数据里面包含的内容可能比较多,如图片之类,比较消耗内存的东西,如果一下子把这些数据全部加载上去,虽然listview存在复用view回收机制,但是数据量太大还是会比较消耗时间,暂用内存,另外一方面用户可能不认为他需要这么多,他可能只是看部分,如果全部显示,有浪费流量之嫌疑,所以这个时候我们有必要对listview进行分页。
当然如果你对listview的其他优化方式还不知道或者不太清楚,已经getView()的conventView不太了解,请点击传送门ListView你不知道的事儿
ok,接着上代码吧。
public class MainActivity extends AppCompatActivity { private List<String> mDatas = new ArrayList<>(); private static final String TAG = "----->>>"; private ListView mListView; private boolean isFull = false; private ArrayAdapter<String> mArrayAdapter ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mListView = (ListView) findViewById(R.id.march_list_view); mArrayAdapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,mDatas); mListView.setAdapter(mArrayAdapter); initData(30); initListener(); } private void initData(int count) { int size = 0; if(! mDatas.isEmpty()){ size += mDatas.size() -1; } for (int i = size; i < count; i++) { mDatas.add("小婷,我喜欢你,我要想你表白"+i+"次"); } mArrayAdapter.notifyDataSetChanged(); } private void initListener() { mListView.setOnScrollListener(new AbsListView.OnScrollListener() { /** * 滑动状态监听 * @param view 当前mListview * @param scrollState 滑动状态 */ @Override public void onScrollStateChanged(AbsListView view, int scrollState) { switch (scrollState){ case SCROLL_STATE_TOUCH_SCROLL: Log.i(TAG, "SCROLL_STATE_TOUCH_SCROLL: 手指滑动屏幕,并且在屏幕上" ); break; case SCROLL_STATE_IDLE: if(isFull){ initData((mDatas.size()+10)); } Log.i(TAG, "SCROLL_STATE_IDLE: 屏幕停止滑动"+" isFull = "+isFull); break; case SCROLL_STATE_FLING: Log.i(TAG, "SCROLL_STATE_FLING: 手指抬起,屏幕惯性滑动"); break; } } /** * 对于适配器视图我们可以总结以下几点,确保无误: 一:初始化listview 二:初始化数据 三:创建适配器 四:适配器关联ListView * @param view * @param firstVisibleItem 屏幕上最顶端view的position * @param visibleItemCount 屏幕范围内view的个数 * @param totalItemCount 数据源大小通过listview的getViewCount()获取 */ @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if(totalItemCount == (firstVisibleItem + visibleItemCount)){ isFull = true; } Log.i(TAG, "onScroll: firstVisibleItem = "+firstVisibleItem+" visibleItemCount = "+visibleItemCount+" totalItemCount = "+totalItemCount); } }); }
接下来启动app看能打印什么,
可以发现即使在listview未滑动仍然执行了onScroll()方法,但是真的未滑动吗?这个可以思考一下,看看我的适配器,再看一看notify,你就会明白些什么。
加一张图来理解O你scroll()方法的参数:
有人问为什么不是24-4尼?那你掰着手指从一数到四是几,然后用4减一,就明白了。而多的一个是由于那个蓝条未消失仍然计算在内(边距不属于3)
接下来我们轻轻滑动一下看看会打印什么。
当我们手指接触到屏幕会触发O你Scroll State Change()方法,就是滑动发生了改变,然后在手指点击与抬起这一个过程中会多次执行onScrollview()方法。其中isFull是用来控制是否增加数据控制的boolean变量。
然而如果我们在滑动屏幕没有抛得动作,也就是,当手指抬起额时候没有在前后移动,这时候还会和上边一样吗?
可见此时监听不到OnScrollStateChange( )Fling屏幕惯性滑动状态。
由于使用的是genymotion暂时不会截屏录像,望谅解,那么当我们滑动到第一次数据的底时会发生什么尼。
可以看见当我们滑倒30的时候就会致使
totalItemCount == (firstVisibleItem + visibleItemCount)成立, 然后导致isFull为true,然后加载更多的数据,可见截图已经出现了31. 眼尖的朋友可能在嘲笑为什么有两个29,哈哈,请看initData(),有一个mData.Size()-1.
ok,今晚到此结束,祝大家晚安。
一家之言,有误望君扶正,多谢。