Android Material日期选择器卡顿问题优化指导
Material Date Picker 日期选择卡顿优化方案
问题场景
在Android应用中使用Material Date Picker实现日期范围选择时,出现打开耗时久、选择操作卡顿延迟的情况,相关实现代码如下:
日期选择器实现代码
fun showDatePicker(activity: Activity, fragmentManager: FragmentManager, onDateSelected: (startDate: String, endDate: String) -> Unit) { val constraintsBuilder = CalendarConstraints.Builder() val calendar = Calendar.getInstance() calendar.add(Calendar.YEAR, -1) // 1 yr ago val minDate = calendar.timeInMillis constraintsBuilder.setStart(minDate) calendar.add(Calendar.YEAR, 2) // max yr 2 years from now val maxDate = calendar.timeInMillis constraintsBuilder.setEnd(maxDate) val dateRange = MaterialDatePicker.Builder.dateRangePicker() .setTitleText("Select dates") .setSelection(Pair(null, null)) .setCalendarConstraints(constraintsBuilder.build()) // Apply the constraints .build() val simpleDateFormat = SimpleDateFormat("dd MMMM yyyy", Locale.getDefault()) dateRange.show(fragmentManager, "DATE_RANGE_PICKER") dateRange.addOnPositiveButtonClickListener { selection -> val startDate = simpleDateFormat.format(selection.first) val endDate = simpleDateFormat.format(selection.second) Log.e("date---->>>>","not-formatted $selection.first") Log.e("date---->>>>","formatted $startDate") onDateSelected(startDate, endDate) } }
Fragment中调用代码
binding.calendar.setOnClickListener { showDatePicker(requireActivity(), requireActivity().supportFragmentManager) { startDate, endDate -> binding.selectedDate.text = "$startDate - $endDate" val firstDate=startDate val lastDate=endDate } }
优化建议
复用Calendar实例并简化日期计算
简化Calendar操作逻辑,避免重复的日期偏移计算,减少不必要的实例操作开销:val calendar = Calendar.getInstance() // 直接链式操作获取最小日期 val minDate = calendar.apply { add(Calendar.YEAR, -1) }.timeInMillis // 从-1年直接偏移3年到+2年,简化计算步骤 calendar.add(Calendar.YEAR, 3) val maxDate = calendar.timeInMillis缓存SimpleDateFormat实例
SimpleDateFormat创建成本高且线程不安全,每次点击都创建新实例会增加性能损耗。可以将其定义为类级别缓存对象:// 在工具类或Fragment内部定义懒加载的日期格式化实例 private val dateFormat by lazy { SimpleDateFormat("dd MMMM yyyy", Locale.getDefault()) }之后在
showDatePicker方法中直接复用该实例,无需每次初始化。提前初始化核心对象(高频场景)
如果该日期选择器属于高频使用控件,可以在Fragment的onViewCreated阶段提前初始化CalendarConstraints和Picker实例(注意避免内存泄漏,不要长期持有),点击时直接调用show方法,减少点击后的初始化耗时。升级Material Components依赖版本
旧版本的Material Date Picker可能存在性能缺陷,确保使用最新稳定版的依赖:implementation 'com.google.android.material:material:1.12.0' // 替换为当前最新稳定版缓存FragmentManager实例
避免每次点击都调用requireActivity().supportFragmentManager,提前在Fragment生命周期内缓存实例:private lateinit var cachedFragmentManager: FragmentManager override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) cachedFragmentManager = requireActivity().supportFragmentManager // 其他初始化逻辑 } // 点击事件中使用缓存的实例 binding.calendar.setOnClickListener { showDatePicker(requireActivity(), cachedFragmentManager) { startDate, endDate -> binding.selectedDate.text = "$startDate - $endDate" } }移除冗余调试日志
发布版本中保留Log.e会增加性能开销,建议仅在调试阶段保留,正式发布时移除或通过编译开关控制日志输出。
内容的提问来源于stack exchange,提问作者Ayush
相关产品推荐
相关产品推荐

