java - Android ListView.notifyDataSetChanged 导致不正确的行

标签 java android kotlin android-listview

我正在开发一个 Android 项目,其中 ListFragment 正在从子 Activity 中更新。然而,尽管更新后元素的计数是正确的,但元素本身却不正确。错误的元素被放入列表中并相互重复。

问题是,在子 Activity 修改文件并调用 populate() 函数之后,然后我返回到 Fragment 所在的主 Activity ,就会出现问题。 例如,一开始它们的顺序是:[1, 2, 3]

现在子 Activity 中的文件操作将项目“1”删除(不是直接调用remove,而是删除该文件,并且populate()函数(下面列出)将生成一个列表没有该元素),它应该变成 [2, 3]。但它变成了 [1, 2]

通过按钮调用完全刷新后,包括清除和重新填充 MetadataManager.packMapPackListManager.onlineListPackListManager.localList ,然后重启MainActivity,就恢复正常了。

现在我们有[2, 3]。子 Activity 中的另一个文件操作应该返回“1”,并且它应该再次变为 [1, 2, 3]。但是,它变成了 [2, 3, 3]

元素来自单例中的 ArrayList。这是 ListFragment 的类:

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 保持不变。

我在谷歌上搜索过这样的问题,但我似乎找不到一个好的答案。我真的很抱歉发布这么长的代码,但我自己真的无法弄清楚。任何帮助将不胜感激!

顺便说一句,我不是母语人士,因此对帖子中的错误感到抱歉。

最佳答案

不要使用ListView,因为它已经过时了,可以尝试使用RecyclerView

关于java - Android ListView.notifyDataSetChanged 导致不正确的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60078368/

相关文章:

android - FragmentManager提交后执行功能

java - org.springframework.beans.factory.UnsatisfiedDependencyException : Error creating bean with name

android - React Navigation 'beforeRemove' 事件未在 React Native 中触发

java - 如何使用 Selenium 从表格中提取 HTML 链接?

android - 每次 Gradle 运行时都会编译应用程序,占用大量时间

android - Xamarin带有AppCompat主题的Android启动表单注释

kotlin - LocalDateTime 扩展功能和智能转换

android - viewBinding为什么让XML根全屏

java - Java 递归暴力迷宫求解器

java - 从 YouTube API 获取用户名和 channel ID