填充 ListView 很慢,Fragment 加载不顺畅

Posted

技术标签:

【中文标题】填充 ListView 很慢,Fragment 加载不顺畅【英文标题】:Populating ListView is slow, Fragment not loading smoothly 【发布时间】: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
    

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

【问题讨论】:

【参考方案1】:

在你的TimetableFragmentAdapter 覆盖destroyItem()

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

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

【讨论】:

感谢您的回答。我应该如何销毁片段?你能解释一下这如何有助于解决问题吗?我还没收到呢。

以上是关于填充 ListView 很慢,Fragment 加载不顺畅的主要内容,如果未能解决你的问题,请参考以下文章

从 Activity 完成异步后在 Fragment 上填充 ListView

从 Parent 为 Fragment 的 ListView 设置适配器

安卓开发 viewpage加fragment加listview. 我想实现一个类似微信的界面。

求教android studio大神:用fragment写一个导航栏,在每个fragment里面加listview,能实现点击事件

安卓ScrollView中放ViewPager+ViewPager,ViewPager中放的是2个Fragment,Fragment中放Listview.

Fragment 中的 ArrayAdapter - Android