ExpandableListAdapter 显示错误的 childViews

问题描述

我正在编写一个应用程序来显示药物组、药物及其信息的树状视图。本质上,它是一个药物组的 ExpandableListView,它在孩子们查看时显示单个药物名称,并在点击时打开一个包含更多信息的新片段。

我一直坚持用正确的数据填充子视图。适配器似乎正确获取了组数据,并且从日志记录和调试来看,子数据似乎也被正确传递。但是, ExpandableListView 中 childViews 中的文本仅对我打开的第一组正确,下一组显示看似随机内容(打开顺序无关紧要)。 childViews 的数量是正确的。详细视图 (onClick) 显示正确的信息,按下后退按钮后,菜单显示正确的信息(但是,任何新打开的组仍然显示错误内容)。

我至少做了 20 轮检查和澄清任何可疑代码,但无济于事。

用于说明的屏幕截图:

list view with two groups expanded

detail view,showing correct info (but not matching that shown in list view)

list view upon returning (notice contents now shown correctly)

这是 expandablelistadapter

class Medicationslistadapter(
    private val context: Context,private val groupList: List<String>,private val itemList: List<List<String>>
) : Baseexpandablelistadapter() {

    override fun getGroupCount(): Int {
        return groupList.size
    }

    override fun getChildrenCount(groupPosition: Int): Int {
        return itemList[groupPosition].size
    }

    override fun getGroup(groupPosition: Int): List<String> {
        return itemList[groupPosition]
    }

    override fun getChild(groupPosition: Int,childPosition: Int): String {
        return itemList[groupPosition][childPosition]
    }

    override fun getGroupId(groupPosition: Int): Long {
        return groupPosition.toLong()
    }

    override fun getChildId(groupPosition: Int,childPosition: Int): Long {
        return childPosition.toLong()
    }

    override fun hasstableIds(): Boolean {
        return true
    }

    override fun getGroupView(
        groupPosition: Int,isExpanded: Boolean,convertView: View?,parent: ViewGroup?,): View {
        var groupView = convertView
        if (groupView == null) {
            val layoutInflater =
                this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
            groupView = layoutInflater.inflate(R.layout.medication_list_group,null)

            val groupTextView: TextView = groupView.findViewById(R.id.text_group_name)
            groupTextView.text = groupList[groupPosition]
        } else return groupView
        return groupView
    }

    override fun getChildView(
        groupPosition: Int,childPosition: Int,isLastChild: Boolean,parent: ViewGroup?
    ): View {
        var childView = convertView
        if (childView == null) {
            val layoutInflater =
                this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
            childView = layoutInflater.inflate(R.layout.medication_list_item,null)

            childView.findViewById<TextView>(R.id.text_medication_name).text = getChild(groupPosition,childPosition)

        } else return childView
        return childView
    }

    override fun isChildSelectable(groupPosition: Int,childPosition: Int): Boolean {
        return true
    }
}

这是详细视图片段:

class MedicationItemFragment : Fragment() {

    private lateinit var medicationName: String

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        //get medication name from SafeArgs
        arguments?.let {
            medicationName = it.getString("medicationName").toString()
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_medication_item,container,false)
    }

    override fun onViewCreated(view: View,savedInstanceState: Bundle?) {
        super.onViewCreated(view,savedInstanceState)

        // get the correct medication data
        val medication: Medication = MedicationsListData().getMedication(medicationName)

        // populate the view with current medication's data
        view.findViewById<TextView>(R.id.text_pharmacodynamics_body).text =
            medication.pharmacodynamics
        view.findViewById<TextView>(R.id.text_contraindications_body).text =
            medication.contraindications
    }

    companion object {
        fun newInstance(): ParametersFragment = ParametersFragment()
    }
}

这是提供适配器数据的类:

class GroupListData {
    fun getItemData(): List<List<String>> {
        return listof(
            listof("amoxicillin + clavulanate","penicillin","clindamycin","vancomycin"),listof("epinephrine","norepinephrine","dopamine"),listof("metoprolol","adenosine","amiodarone"),listof("metoclopramide")
        )
    }

    fun getGroupData(): List<String> {
        return listof(
            "antibiotics","vasopressors","antiarrhythmics","antiemetics"
        )
    }
}

如有必要,我可以详细说明或解释任何内容。非常感谢任何帮助!

解决方法

阅读后我现在明白问题是回收视图没有正确填充。对此的解决方法是停止回收视图并为每个孩子创建一个新视图:

    override fun getChildView(
        groupPosition: Int,childPosition: Int,isLastChild: Boolean,convertView: View?,parent: ViewGroup?
    ): View {
        var childView = convertView
        val layoutInflater = this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
        childView = layoutInflater.inflate(R.layout.medication_list_item,null)

        val medicationName = GroupListData().getItemData()[groupPosition][childPosition]
        val medication: Medication = MedicationsListData().getMedication(medicationName)

        childView.findViewById<TextView>(R.id.text_medication_name).text = medication.medicationName
        if(medication.brandName != "null") {
            childView.findViewById<TextView>(R.id.text_brand_name).text = medication.brandName
        }

        return childView
    }

我不会完全认为这是一种解决方法,因为(非回收)视图的数量可能会导致一些性能问题。但是,如果其他任何人都在为同样的问题而苦苦挣扎(并且没有预料到性能问题),这很有效。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...