ListView 它们的优化你真的懂吗
listView
有一天,我用到 recyclerView 发觉我对他的复用只存在使用,而我更加忘记了 LIstView 是如何优化的,由此,打算记录一下。稍后会有 RecyclerView 的理解
常用的四种优化方式
- 复用 convertView
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
//如果当前的convertView为null,则通过inflate产生一个view
convertView = View.inflate(context, R.layout.item_layout,null);
}
return convertView;
}
- ViewHolder 的使用,用以解决每次 FindviewById 的耗时操作
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View itemView = null;
if (convertView == null) {
itemView = View.inflate(context, R.layout.item_news_data, null);
holder = new ViewHolder(itemView);
//用setTag的方法把ViewHolder与convertView "绑定"在一起
itemView.setTag(holder);
} else {
//当不为null时,我们让itemView=converView,用getTag方法取出这个itemView对应的holder对象,就可以获取这个itemView对象中的组件
itemView = convertView;
holder = (ViewHolder) itemView.getTag();
}
JavaBean javaBean = mListDatas.get(position);
holder.title.setText(javaBean.title);
holder.content.setText(javaBean.content);
return itemView;
}
-
数据分页加载
每次加载大于屏幕长度的数目,滑动的时候继续加载 -
管理 adapter 的数据集合 list , 一定策略覆盖 list 中上一部分数据。
重点解释一下第一点,listview 为什么能复用 convertView ?在代码中,我们找到 listview 的父类 AbsListView;RecycleBin 是主要的缓存机制。
注意到 ArrayList[] mScrapViews; 这是个 View 的数组;这里面装载的是滑出屏幕的 View ,为什么是数组尼,这是为了处理 listView 的多种类型条目。
mViewTypeCount 表示了 item 的种类,会根据 getItemViewType 取出相应的复用的
mScrapViews ;
从上面可以看到会从找到相同类型的 scrapViews 删除相应的 View,并返回。为什么会删除,因为每次滑出屏幕都会向这个集合中添加一个元素。
在 AbsListView 的 onLayout 中将会调用到 obtainView
View obtainView(int position, boolean[] outMetadata) {
......
// Check whether we have a transient state view. Attempt to re-bind the
// data and discard the view if we fail.
final View transientView = mRecycler.getTransientStateView(position);
if (transientView != null) {
final LayoutParams params = (LayoutParams) transientView.getLayoutParams();
// If the view type hasn't changed, attempt to re-bind the data.
if (params.viewType == mAdapter.getItemViewType(position)) {
final View updatedView = mAdapter.getView(position, transientView, this);
// If we failed to re-bind the data, scrap the obtained view.
if (updatedView != transientView) {
setItemViewLayoutParams(updatedView, position);
mRecycler.addScrapView(updatedView, position);
}
}
outMetadata[0] = true;
// Finish the temporary detach started in addScrapView().
transientView.dispatchFinishTemporaryDetach();
return transientView;
}
// scrapView 有值得话,会删除集合中中的 view,因此后面会 addScrapView
final View scrapView = mRecycler.getScrapView(position);
// 这里就是刚刚重点分析取出屏幕的 view 的地方,所以在 getView 能获取到 一个已经 inflate 的 View。
final View child = mAdapter.getView(position, scrapView, this);
if (scrapView != null) {
if (child != scrapView) {
// Failed to re-bind the data, return scrap to the heap.
mRecycler.addScrapView(scrapView, position);
} else if (child.isTemporarilyDetached()) {
outMetadata[0] = true;
// Finish the temporary detach started in addScrapView().
child.dispatchFinishTemporaryDetach();
}
}
........
return child;
}