场景:之前原生项目开发中,遇到了动态2级表格需求,最开始使用viewGroup的addview()方法,动态对表格内容进行添加。但发现动态添加时,会导致渲染速度十分缓慢,在请求获取到数据后,过了好几秒才渲染完成。
分析:在查阅资料后,注意到了另一个view添加方法----addViewInLayout。该方法大致介绍为:在布局期间添加视图,如果你需要添加多个view,那么这个方法更加有用。如果index是负的,那将会放在最后一个。(大致就是这么个意思,人工翻译可能稍微有点偏差)
/**
* Adds a view during layout. This is useful if in your onLayout() method,
* you need to add more views (as does the list view for example).
*
* If index is negative, it means put it at the end of the list.
*
* @param child the view to add to the group
* @param index the index at which the child must be added or -1 to add last
* @param params the layout parameters to associate with the child
* @param preventRequestLayout if true, calling this method will not trigger a
* layout request on child
* @return true if the child was added, false otherwise
*/
protected boolean addViewInLayout(View child, int index, LayoutParams params,
boolean preventRequestLayout) {
if (child == null) {
throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup");
}
child.mParent = null;
addViewInner(child, index, params, preventRequestLayout);
child.mPrivateFlags = (child.mPrivateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
return true;
}
具体使用:我这边定义了一个容器组件,作为二级表格的子组件,对外暴露setView方法,外层循环列表数据,循环调用setView方法进行子view的添加。其中,view参数对需要添加的子view,对应源码中的child参数;i对应源码中的index,一般i++自增就行。
/**
* @author Flash
* @date 2020-05-13 11:40
* @description 用于添加View的LinearLayout,优化直接addView带来的绘制缓慢
*/
public class AddViewLinearLayout extends LinearLayout {
public AddViewLinearLayout(Context context) {
super(context);
}
public AddViewLinearLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public AddViewLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected boolean addViewInLayout(View child, int index, ViewGroup.LayoutParams params) {
return super.addViewInLayout(child, index, params);
}
public void setView(View view, int i){
LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
addViewInLayout(view, i, layoutParams);
}
}
总结:在父组件(父类为ViewGroup的容器)有大量view添加操作时,推荐使用addViewInLayout替换addView,能明显提升渲染速度。对于addViewInLayout和addView的区别,addViewInLayout在所有子view添加完成后再计算与绘制;而addView在每次添加后均调用requestLayout()方法进行计算与绘制;具体可见ViewGroup中的源码。
(如有错误,请指正!)