【问题标题】:Populating ListView is slow, Fragment not loading smoothly填充 ListView 很慢,Fragment 加载不顺畅
【发布时间】:2020-04-17 01:10:43
【问题描述】:

所以我正在使用 AndroidStudio 并在 Kotlin 中编写我的代码。 我有一个带有 TabLayout 和 ViewPager 的片段,它有 5 个标签。每个选项卡都包含另一个带有 ListView 和 ToggleButton 的 Fragment。 ListViews 都包含 10 个项目。 Here is a screenshot, I'm not allowed to use embed images yet

问题是Fragment打开不顺畅,尤其是先打开的时候。

我认为问题在于 5 个选项卡中 ListViews 的 ListViewAdapter 的实现,尤其是 getView 函数。 这是他们的代码:

    inner class TimetableListAdapter(
        private val _context : Context,
        private var fulldata : TimetableUtility.TimetableDay,
        var bWeek : Boolean,
        private var dayData : ArrayList<TimetableUtility.TimetableSubject> = fulldata[0],
        private val _resource : Int = R.layout.timetable_subject_element
    ) : ArrayAdapter<TimetableUtility.TimetableSubject>(_context, _resource, dayData){

        init {
            dayData = if(bWeek){
                fulldata[1]
            }else{
                fulldata[0]
            }
            Log.d("Timetable" , "Adapter init ")
        }

        override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {

            Log.d("Timetable" , "getView: $bWeek")

            val s : TimetableUtility.TimetableSubject = if(bWeek){
                dayData = fulldata[1]
                fulldata[1][position]
            }else{
                dayData = fulldata[0]
                fulldata[0][position]
            }

            val v =
                convertView
                    ?: LayoutInflater.from(_context).inflate(
                        _resource,
                        parent,
                        false
                    )

            v.editIcon.setOnClickListener {
                openEditDialog(this@TimetableDayFragment.context!!,s)
            }

            v.timetable_hour_number.text = (position + 1).toString()
            v.timetable_subject_title.text = s.name
            v.timetable_subject_room.text = s.room

            return v
        }
    }

我知道 ViewHolder 模式的实现会减少视图搜索调用的次数,但我认为这不会影响初始生成。

我在 AndroidStudio 中使用 Profiler 玩了一下,发现在我的电脑上的虚拟机上运行应用程序时,适配器的 getView 方法大约需要 20-30 毫秒。在我的三星设备(Galaxy A6,不是那么旧)上运行应用程序时,它会更多,因为延迟更大。我还没有使用分析器。

我的假设是,getView 方法导致的延迟是否正确,如果是,您对如何改进有任何建议或想法?

如果有帮助,这里是 ViewPager 适配器的代码:

    inner class TimetableFragmentAdapter(
        context : Context,
        fm : FragmentManager,
        private val totalTabs : Int
    ) : FragmentPagerAdapter(fm,totalTabs){

        private val dayTitles = arrayOfNulls<String>(5)
        private var sdf =
            SimpleDateFormat("EEE", Locale.getDefault())
        private var calendar = Calendar.getInstance()!!

        init{
            for (i in 0..4) {
                calendar.set(Calendar.DAY_OF_WEEK, i + 2)
                dayTitles[i] = sdf.format(calendar.time)
            }
        }

        override fun getCount(): Int {
            return totalTabs
        }

        override fun getPageTitle(position: Int): CharSequence? {
            return dayTitles[position]
        }

        @RequiresApi(Build.VERSION_CODES.O)
        override fun getItem(position: Int): Fragment {
            when(position){
                0 -> return TimetableDayFragment(DayOfWeek.MONDAY, this@TimetableFragment)
                1 -> return TimetableDayFragment(DayOfWeek.TUESDAY, this@TimetableFragment)
                2 -> return TimetableDayFragment(DayOfWeek.WEDNESDAY, this@TimetableFragment)
                3 -> return TimetableDayFragment(DayOfWeek.THURSDAY, this@TimetableFragment)
                4 -> return TimetableDayFragment(DayOfWeek.FRIDAY, this@TimetableFragment)
            }
            return TimetableDayFragment(DayOfWeek.MONDAY, this@TimetableFragment)
        }

以及用于每个选项卡的内部片段的创建代码

override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val root = inflater.inflate(R.layout.timetable_inner_fragment,container,false)

        adapter = TimetableListAdapter(context!!, TimetableUtility.timetable.get(day), root.weekSwitch.isChecked)
        root.timetable_list.adapter = adapter

        root.weekSwitch.setOnCheckedChangeListener{
                it, selected ->
            (root.timetable_list.adapter as TimetableListAdapter).bWeek = selected
            (root.timetable_list.adapter as TimetableListAdapter).notifyDataSetChanged()
        }

        return root
    }

非常感谢您提前提供的帮助和想法。 如果您需要更多代码或信息,请告诉我。

【问题讨论】:

    标签: android listview android-fragments layout layout-inflater


    【解决方案1】:

    在你的TimetableFragmentAdapter 覆盖destroyItem()

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
    // destroy your fragment view here
    }
    

    关注这个问题How to remove fragment from fragmentPagerAdapter

    【讨论】:

    • 感谢您的回答。我应该如何销毁片段?你能解释一下这如何有助于解决问题吗?我还没收到呢。
    猜你喜欢
    • 2012-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多