android - 理解转换 View

标签 android android-listview custom-adapter

我想了解 convertView 的工作原理。我确实阅读了我遇到的大部分文档以及关于 StackOverflow 的问题。我以为我已经理解它是如何工作的,但在实现时,我无法正确理解。

我现在的代码:

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    if(Const.DEBUGGING){
        Log.d(Const.DEBUG, "Position = "+position);
    }

    if (convertView == null) {

        if(Const.DEBUGGING){
            Log.d(Const.DEBUG, "convertView is NULL");
        }

        convertView = getActivity().getLayoutInflater().inflate(
                R.layout.item_mtf_results, parent, false);

        holder = new ViewHolder();
        holder.txtViewResults = (TextView) convertView
                .findViewById(R.id.textview_item_mtf_results);

        convertView.setTag(holder);
    } else {

        if(Const.DEBUGGING){
            Log.d(Const.DEBUG, "convertView is NOT Null");
        }

        holder = (ViewHolder) convertView.getTag();
    }

    holder.txtViewResults.setText(dummyText[position]);

    return convertView;
}

上面代码的我的 Logcat:

03-30 10:27:29.433: D/TYM(29043): Position = 0
03-30 10:27:29.433: D/TYM(29043): convertView is NULL
03-30 10:27:29.433: D/TYM(29043): Position = 1
03-30 10:27:29.433: D/TYM(29043): convertView is NOT Null
03-30 10:27:29.433: D/TYM(29043): Position = 2
03-30 10:27:29.433: D/TYM(29043): convertView is NOT Null
03-30 10:27:29.433: D/TYM(29043): Position = 3
03-30 10:27:29.433: D/TYM(29043): convertView is NOT Null
03-30 10:27:29.433: D/TYM(29043): Position = 4
03-30 10:27:29.433: D/TYM(29043): convertView is NOT Null
03-30 10:27:29.433: D/TYM(29043): Position = 5
03-30 10:27:29.433: D/TYM(29043): convertView is NOT Null
03-30 10:27:29.433: D/TYM(29043): Position = 6
03-30 10:27:29.433: D/TYM(29043): convertView is NOT Null
03-30 10:27:29.433: D/TYM(29043): Position = 7
03-30 10:27:29.433: D/TYM(29043): convertView is NOT Null
03-30 10:27:29.433: D/TYM(29043): Position = 8
03-30 10:27:29.433: D/TYM(29043): convertView is NOT Null
03-30 10:27:29.453: D/TYM(29043): Position = 0
03-30 10:27:29.453: D/TYM(29043): convertView is NOT Null
03-30 10:27:29.453: D/TYM(29043): Position = 1
03-30 10:27:29.453: D/TYM(29043): convertView is NULL
03-30 10:27:29.453: D/TYM(29043): Position = 2
03-30 10:27:29.453: D/TYM(29043): convertView is NULL
03-30 10:27:29.453: D/TYM(29043): Position = 3
03-30 10:27:29.453: D/TYM(29043): convertView is NULL
03-30 10:27:29.453: D/TYM(29043): Position = 4
03-30 10:27:29.453: D/TYM(29043): convertView is NULL
03-30 10:27:29.463: D/TYM(29043): Position = 5
03-30 10:27:29.463: D/TYM(29043): convertView is NULL
03-30 10:27:29.463: D/TYM(29043): Position = 6
03-30 10:27:29.463: D/TYM(29043): convertView is NULL
03-30 10:27:29.463: D/TYM(29043): Position = 7
03-30 10:27:29.463: D/TYM(29043): convertView is NULL
03-30 10:27:29.463: D/TYM(29043): Position = 8
03-30 10:27:29.463: D/TYM(29043): convertView is NULL
03-30 10:27:29.503: D/TYM(29043): Position = 0
03-30 10:27:29.503: D/TYM(29043): convertView is NULL
03-30 10:27:29.503: D/TYM(29043): Position = 1
03-30 10:27:29.503: D/TYM(29043): convertView is NOT Null
03-30 10:27:29.503: D/TYM(29043): Position = 2
03-30 10:27:29.503: D/TYM(29043): convertView is NOT Null
03-30 10:27:29.503: D/TYM(29043): Position = 3
03-30 10:27:29.503: D/TYM(29043): convertView is NOT Null
03-30 10:27:29.503: D/TYM(29043): Position = 4
03-30 10:27:29.503: D/TYM(29043): convertView is NOT Null
03-30 10:27:29.503: D/TYM(29043): Position = 5
03-30 10:27:29.503: D/TYM(29043): convertView is NOT Null
03-30 10:27:29.503: D/TYM(29043): Position = 6
03-30 10:27:29.503: D/TYM(29043): convertView is NOT Null
03-30 10:27:29.503: D/TYM(29043): Position = 7
03-30 10:27:29.503: D/TYM(29043): convertView is NOT Null
03-30 10:27:29.503: D/TYM(29043): Position = 8
03-30 10:27:29.503: D/TYM(29043): convertView is NOT Null

截图:

enter image description here

根据我对 convertView 的了解,第一次在 ListView 中加载项目时,内存仅分配给那些在屏幕中加载的 View ,还有一些额外的缓冲区。当我们开始滚动时,离开屏幕的 View 将被回收到现有 View 中。

因此,当屏幕第一次加载时,convertView 将为 NULL,因此会分配内存。只有当我们开始滚动并且 View 可用于回收时,convertView 才不会为 Null。这样对吗?

上面的 Logcat 显示了我第一次加载屏幕时的日志。

我的问题:

  1. 为什么所有 View 都有 3 个调用。刚刚第一次加载屏幕....
  2. 为什么第二个位置的convertView NOT NULL?
  3. 为什么第二次循环convertView又是NULL?

最佳答案

为了更好地理解发生了什么,在 getView() 中放置一个调试器断点并检查调用堆栈跟踪以查看调用的原因。

您的 ListView 似乎处于需要多次测量/布局 channel 的复杂布局中。例如。 LinearLayout 具有权重或 RelativeLayout 具有子项之间的依赖关系。

要测量 ListView,必须测量可见的子级。这解释了对 getView() 的一次这样的调用,对于两遍布局,两次。此外,出于测量目的, View 可以立即回收,因为它们还不需要显示在屏幕上。

寓意:避免将适配器 View 放置在多 channel 布局中。尽可能避免多遍布局。

关于android - 理解转换 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22740550/

相关文章:

android - 什么是适配器中的转换 View ?它是如何运作的?

android - java.lang.IllegalStateException :getWritableDatabase called recursively 错误

java - com.SearchPlayer 不是一个封闭类

android - 为什么 Jelly Bean 不在通知中显示第二行?

android - 我什么时候应该将我的 Android 应用程序定义为不可移动到 SD 卡 (installLocation=internalOnly)?

java - 尝试使用按钮传递项目和子项目

java - 如何动态设置形成 ListView 行的多个 TextView 中的文本大小?

Android 删除 SQLite 表

android - 如何使用 CursorAdapter 将 Filter 设置为 ListView?

android - 为什么在onCreate之外使用MediaPlayer会导致错误