场景:文件浏览器加载大容量磁盘过程中,列表浏览和平铺浏览点击进入下一级界面或者按遥控器快速移动光标,概率性会有卡顿现象。
分析原因:列表浏览使用的是ListView, 平铺浏览使用的是GridView, 可能是重复调用了getView或者getView方法里面做了耗时的操作。(加载大容量磁盘时,系统需要扫描媒体库,也可能会使CPU占用高而导致卡顿,这种情况暂不考虑)
一、ListView重复调用getView解决方法:
1、首先在getView方法中加上打印日志,代码如下:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.d(TAG, "getView: position = " + position);
2、打印日志如下,标记为红框的地方为getView重复调用:
3、原因分析及解决方法:ListView布局时height和width都不是match_parent,导致不断计算高度,不断刷新。或者说它的父容器没有设置成match_parent. 我们只需要设置ListView为固定宽高即可。
listView布局xml文件修改前:
修改后:
修改后编译APK再次打印日志如下(ListView没有重复调用getView了):
二、GridView重复调用getView解决方法:
1、首先在getView方法中加上打印日志,代码如下:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
int childCount = parent.getChildCount();
Log.d(TAG, "getView: position = " + position + ", childCount = " + childCount);
2、打印日志如下,标记为红框的地方为getView重复调用:
3、原因分析及解决方法:GridView宽高设置为match_parent, 仍会出现多次调用getView的问题。由上面日志可以看到,当position != childCount 且position = 0且时,此时为getView重复调用。虽然暂无好的方法禁止GridView重复调用getView, 但我们可以判断重复调用getView时,直接返回convertView即可。
代码修改前:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
int childCount = parent.getChildCount();
Log.d(TAG, "getView: position = " + position + ", childCount = " + childCount);
ViewHolder vh;
if (convertView == null) {
vh = new ViewHolder();
代码修改后:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
int childCount = parent.getChildCount();
Log.d(TAG, "getView: position = " + position + ", childCount = " + childCount);
ViewHolder vh;
// 按方向键或者ImageLoader加载缩略图都会重复调用两次getView,导致卡顿。当判断为重复调用时直接返回convertView
if (position != childCount && position == 0 && convertView != null) {
Log.d(TAG, "getView duplicate, return");
return convertView;
}
if (convertView == null) {
vh = new ViewHolder();
修改后编译APK再次打印日志如下(当判断为重复调用getView时直接返回):
PS:以上代码中打印日志只是供调试,由于getView日志打印很频繁,正式提交代码时需要屏蔽掉该日志打印。