在我一直在努力的应用中,我有一个自定义课程DeviceListAdapter
,其中BaseAdapter
传递给我的ListView
。在我的DeviceListAdapter
课程中,我保留了自己的ArrayList<Device>
,用于生成View getView(... )
的列表视图。每当应用导致数据发生变化时,我都会使用DeviceListAdapter
中的自定义方法更新ArrayList<Device>
以反映更改。我已经使用调试器和许多print语句检查数据是否按照我预期的方式更改,添加和删除指定的Device
个对象。但是,在每次更改数据后,我也会调用notifyDataSetChanged()
,但在UI上没有任何元素会更新。在调试器中,我发现在调用notifyDataSetChanged()
后,getView(... )
方法未被调用,这解释了为什么ListView
没有被重绘。为了找出原因,我使用了调试器&#34;进入&#34;函数跟踪程序执行进入android框架的位置,因为我已经下载了SDK源代码。我发现的非常有趣。执行的路径是这样的:
DeviceListAdapter.notifyDataSetChanged()
BaseAdapter.notifyDataSetChanged()
DataSetObservable.notifyChanged()
AbsListView.onInvalidated()
而是调用onChanged()
方法,它跳过轨道并在onInvalidated()
方法到达AbsListView
后执行。最初我认为这是一个错误,调试器可能读错了行号,但我重新启动了我的Android Studio以及完全卸载并重新安装了应用程序,但结果是一样的。任何人都可以告诉我这是否是Android架构的合法问题,或者调试器是否不可靠,无法跟踪我自己的项目文件之外的执行?
有关notifyDataSetChanged()
的实施的更多信息...我创建了覆盖BaseAdapter
notifyDataSetChanged()
的本地方法,以便设置布尔标志{{1}我的mForceRedraw
内部是否应该强制重绘我的列表条目。在DeviceListAdapter
方法中,我通常会检查第二个参数getView(... )
是否为空,如果是,那么我重绘视图,如果没有,那么我将convertView传递给它并返回它。但是,当&#39; mForceRedraw&#39;是的,我永远不会返回View convertView
,我明确地重绘了视图。出现的问题是由我之前的担忧造成的,即我执行convertView
后未调用getView()
。
编辑:这是我notifyDataSetChanged()
的代码段:
DeviceListAdapter
答案 0 :(得分:1)
notifyDataSetChanged()
存在许多错误,如果您尝试对列表数据进行一些复杂的工作,通常会出现错误。
大多数情况下,这是因为该方法是懒惰的,无法区分更改,因此要避免此问题,请使用以下方案测试代码:
notifyDataSetChanged()
notifyDataSetChanged()
并告诉我它是否解决了你的问题。
编辑:放入适配器代码后,我看到了代码中的缺陷。
对不起迟到的回复:
convertView
是您在初始化之前填充的视图。
当在方法getView()
中获得convertView
的实例时,必须在返回之前填充它。
所以要明确,做这样的事情:
public View getView(final int position, View convertView, ViewGroup parent) {
View view;
if (convertView == null) //Regenerate the view
{
/* Instantiate your view */
} else {
view = convertView;
}
// populate the elements in view like EditText, TextView, ImageView and etc
return view;
}
答案 1 :(得分:1)
您在适配器中并且调用通知数据集已更改。理想情况下甚至不需要。因为正在修改适配器内部使用的数据集。适配器的getView方法将每当需要渲染视图时总是被调用。
convertView方法是单独回收视图(而不是数据)。它只是为您提供了昂贵的视图通胀过程的替代方法。
那么您的代码应该是什么:
public View getView(final int position, View convertView, ViewGroup parent) {
LinearLayout view;
if (convertView == null) //Regenerate the view
{
/* inflate Draws my views */
} else
{
view = (LinearLayout) convertView;
}
//repopulate this view with the data that needs to appear at this position using getItem(position)
return view;
}