Android ListView.notifyDataSetChanged 导致不正确的行
Android ListView.notifyDataSetChanged causing incorrect rows
我正在做一个 android 项目,其中一个 ListFragment 正在从子 activity 更新。然而,虽然更新后元素的计数是正确的,但元素本身却不是。不正确的元素被放入列表并相互重复。
问题是,子activity修改文件后,调用populate()函数,然后我return到Fragment所在的mainactivity,问题出现了。
例如,一开始它们的顺序是:[1, 2, 3]
现在子进程中的文件操作activity删除了项目“1”(不是直接调用remove,而是删除那个文件,populate()
函数(下面列出)会生成一个没有那个元素的列表),它应该变成 [2, 3]
。但它变成了[1, 2]
。
在通过按钮调用完全刷新后,包括清除和重新填充 MetadataManager.packMap
和 PackListManager.onlineList
、PackListManager.localList
,然后重新启动 MainActivity,它 return恢复正常。
现在我们有 [2, 3]
。子 activity 中的另一个文件操作应该返回“1”,并且它应该再次变为 [1, 2, 3]
。但是,它变成了 [2, 3, 3]
。
元素来自单例中的 ArrayList。这是 ListFragment 的 class:
class PackListFragment : ListFragment() {
private lateinit var dataList: ArrayList<PackageMetadata>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val index = arguments?.getInt(ARG_SECTION_NUMBER) ?: 1
if (index == 1){
dataList = PackListManager.onlineList
} else {
dataList = PackListManager.localList
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val adapter = PackMetadataAdapter(activity as Context, dataList)
listAdapter = adapter
return inflater.inflate(R.layout.fragment_main, container, false)
}
override fun onResume() {
(listAdapter as ArrayAdapter<PackageMetadata>).notifyDataSetChanged()
super.onResume()
}
我的 ListView 使用自定义适配器。这是适配器:
class PackMetadataAdapter (context : Context, val values : List<PackageMetadata>)
: ArrayAdapter<PackageMetadata>(context, -1, values) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
if (convertView == null) {
val inflater = context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
/*val rowView : View = inflater.inflate(android.R.layout.simple_list_item_1, parent, false)
val text1 = rowView.findViewById(android.R.id.text1) as TextView
text1.text = values[position].Name_LO*/
val metadata = values[position]
val rowView: View = inflater.inflate(R.layout.listitem_route, parent, false)
val textTitle = rowView.findViewById<View>(R.id.textTitle) as TextView
val textAuthor = rowView.findViewById(R.id.textAuthor) as TextView
val textVersion = rowView.findViewById(R.id.textVersion) as TextView
val textTimestamp = rowView.findViewById(R.id.textTimestamp) as TextView
val imageView: ImageView = rowView.findViewById<View>(R.id.imageThumbnail) as ImageView
textTitle.text = metadata.Name_LO
textAuthor.text = metadata.Author.Name_LO
textVersion.text = metadata.Version.get()
textTimestamp.text = SimpleDateFormat("yyyy-MM-dd", Locale.US)
.format(values[position].Timestamp)
DownloadImageTask(imageView).execute(metadata.Thumbnail)
return rowView
}
return convertView
}
}
单例中的列表是这样填充的:
object PackListManager {
const val LOGCAT_TAG = "BCSPackListMan"
val localList : ArrayList<PackageMetadata> = ArrayList()
var onlineList : ArrayList<PackageMetadata> = ArrayList()
fun populate(){
localList.clear(); onlineList.clear()
val localPacks = HashMap(PackLocalManager.getLocalPacks().map {
val parts = stripExtension(it.nameWithoutExtension).split("_")
if (parts.count() > 1) {
parts[0] to Version(parts[1])
} else {
it.nameWithoutExtension to Version("0.0")
}
}.toMap())
for (pack in MetadataManager.packMap){
if (localPacks.containsKey(pack.key)){
Log.i(LOGCAT_TAG, "Pack "+pack.key+" found on local disk")
if (localPacks[pack.key]!! < pack.value.Version){
Log.i(LOGCAT_TAG, "Pack "+pack.key+" can be updated")
}
localPacks.remove(pack.key)
localList.add(pack.value)
} else {
Log.i(LOGCAT_TAG, "Pack "+pack.key+" not installed")
onlineList.add(pack.value)
}
}
}
通过检查logcat,我可以说polulate()
函数生成的列表是正确的,而如果没有调用上述手动刷新,MetadataManager.packMap shuold保持不变。
我在google上搜索过这样的问题,但我似乎找不到合适的答案。我真的很抱歉 post 打了这么长的代码,但我自己真的想不通。任何帮助将不胜感激!
顺便说一句,我不是母语人士,所以对于 post 中的错误感到抱歉。
不要用ListView
,因为已经过时了,改用这个试试RecyclerView
.
我正在做一个 android 项目,其中一个 ListFragment 正在从子 activity 更新。然而,虽然更新后元素的计数是正确的,但元素本身却不是。不正确的元素被放入列表并相互重复。
问题是,子activity修改文件后,调用populate()函数,然后我return到Fragment所在的mainactivity,问题出现了。
例如,一开始它们的顺序是:[1, 2, 3]
现在子进程中的文件操作activity删除了项目“1”(不是直接调用remove,而是删除那个文件,populate()
函数(下面列出)会生成一个没有那个元素的列表),它应该变成 [2, 3]
。但它变成了[1, 2]
。
在通过按钮调用完全刷新后,包括清除和重新填充 MetadataManager.packMap
和 PackListManager.onlineList
、PackListManager.localList
,然后重新启动 MainActivity,它 return恢复正常。
现在我们有 [2, 3]
。子 activity 中的另一个文件操作应该返回“1”,并且它应该再次变为 [1, 2, 3]
。但是,它变成了 [2, 3, 3]
。
元素来自单例中的 ArrayList。这是 ListFragment 的 class:
class PackListFragment : ListFragment() {
private lateinit var dataList: ArrayList<PackageMetadata>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val index = arguments?.getInt(ARG_SECTION_NUMBER) ?: 1
if (index == 1){
dataList = PackListManager.onlineList
} else {
dataList = PackListManager.localList
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val adapter = PackMetadataAdapter(activity as Context, dataList)
listAdapter = adapter
return inflater.inflate(R.layout.fragment_main, container, false)
}
override fun onResume() {
(listAdapter as ArrayAdapter<PackageMetadata>).notifyDataSetChanged()
super.onResume()
}
我的 ListView 使用自定义适配器。这是适配器:
class PackMetadataAdapter (context : Context, val values : List<PackageMetadata>)
: ArrayAdapter<PackageMetadata>(context, -1, values) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
if (convertView == null) {
val inflater = context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
/*val rowView : View = inflater.inflate(android.R.layout.simple_list_item_1, parent, false)
val text1 = rowView.findViewById(android.R.id.text1) as TextView
text1.text = values[position].Name_LO*/
val metadata = values[position]
val rowView: View = inflater.inflate(R.layout.listitem_route, parent, false)
val textTitle = rowView.findViewById<View>(R.id.textTitle) as TextView
val textAuthor = rowView.findViewById(R.id.textAuthor) as TextView
val textVersion = rowView.findViewById(R.id.textVersion) as TextView
val textTimestamp = rowView.findViewById(R.id.textTimestamp) as TextView
val imageView: ImageView = rowView.findViewById<View>(R.id.imageThumbnail) as ImageView
textTitle.text = metadata.Name_LO
textAuthor.text = metadata.Author.Name_LO
textVersion.text = metadata.Version.get()
textTimestamp.text = SimpleDateFormat("yyyy-MM-dd", Locale.US)
.format(values[position].Timestamp)
DownloadImageTask(imageView).execute(metadata.Thumbnail)
return rowView
}
return convertView
}
}
单例中的列表是这样填充的:
object PackListManager {
const val LOGCAT_TAG = "BCSPackListMan"
val localList : ArrayList<PackageMetadata> = ArrayList()
var onlineList : ArrayList<PackageMetadata> = ArrayList()
fun populate(){
localList.clear(); onlineList.clear()
val localPacks = HashMap(PackLocalManager.getLocalPacks().map {
val parts = stripExtension(it.nameWithoutExtension).split("_")
if (parts.count() > 1) {
parts[0] to Version(parts[1])
} else {
it.nameWithoutExtension to Version("0.0")
}
}.toMap())
for (pack in MetadataManager.packMap){
if (localPacks.containsKey(pack.key)){
Log.i(LOGCAT_TAG, "Pack "+pack.key+" found on local disk")
if (localPacks[pack.key]!! < pack.value.Version){
Log.i(LOGCAT_TAG, "Pack "+pack.key+" can be updated")
}
localPacks.remove(pack.key)
localList.add(pack.value)
} else {
Log.i(LOGCAT_TAG, "Pack "+pack.key+" not installed")
onlineList.add(pack.value)
}
}
}
通过检查logcat,我可以说polulate()
函数生成的列表是正确的,而如果没有调用上述手动刷新,MetadataManager.packMap shuold保持不变。
我在google上搜索过这样的问题,但我似乎找不到合适的答案。我真的很抱歉 post 打了这么长的代码,但我自己真的想不通。任何帮助将不胜感激!
顺便说一句,我不是母语人士,所以对于 post 中的错误感到抱歉。
不要用ListView
,因为已经过时了,改用这个试试RecyclerView
.