Я сделал все слушатели и ссылки как WeakReference, но тем не менее, это утечка памяти.
DatePickerFragment:
class DatePickerFragment : DialogFragment() {
private var datePickerDialog: WeakReference<DatePickerDialog>? = null
private var listener: WeakReference<DatePickerDialog.OnDateSetListener>? = null
var dateSetListener: DateSet? = null
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
listener = WeakReference(DatePickerDialog.OnDateSetListener { view, year, month, dayOfMonth ->
val selectedDate = ZonedDateTime.now().startOfTheDay().withDayOfMonth(dayOfMonth).withMonth(month.plus(1)).withYear(year)
dateSetListener?.onDateSet(selectedDate, arguments?.getBoolean(REQUIRED_RELOAD)!!)
dismissAllowingStateLoss()
})
// Use the current date as the default date in the picker
val c = Calendar.getInstance()
val year = c.get(Calendar.YEAR)
val month = c.get(Calendar.MONTH)
val day = c.get(Calendar.DAY_OF_MONTH)
// Create a new instance of DatePickerDialog and return it
datePickerDialog = WeakReference(DatePickerDialog(requireActivity(), listener?.get(), year, month, day))
return datePickerDialog!!.get()!!
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
dateSetListener = (activity as DateSet)
}
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
dismissAllowingStateLoss()
}
interface DateSet {
fun onDateSet(date: ZonedDateTime, reload: Boolean)
}
override fun onDestroy() {
Timber.d("onDestroy called")
listener = null
dateSetListener = null
datePickerDialog = null
super.onDestroy()
}
companion object {
const val REQUIRED_RELOAD = "REQUIRED_RELOAD_KEY"
}
}
Показ DatePicker из Activity:
private var dateFragment: WeakReference<DatePickerFragment>? = null
private fun showDatePicker(reload: Boolean) {
dateFragment = WeakReference(DatePickerFragment())
dateFragment?.get()?.arguments = Bundle().apply { putBoolean(REQUIRED_RELOAD, reload) }
dateFragment?.get()?.show(supportFragmentManager, "PaDatePicker")
}
Как вы можете видеть из фрагмента кода, я стараюсь всеми возможными способами исправить утечку, но не повезло. Любая помощь очень ценится.
┬
├─ android.os.HandlerThread
│ Leaking: UNKNOWN
│ Thread name: 'queued-work-looper'
│ GC Root: Java local variable
│ ↓ thread HandlerThread.<Java Local>
│ ~~~~~~~~~~~~
├─ android.os.Message
│ Leaking: UNKNOWN
│ ↓ Message.obj
│ ~~~
├─ android.app.DatePickerDialog
│ Leaking: YES (Dialog#mDecor is null)
│ ↓ DatePickerDialog.mDateSetListener
├─ god.panchang.DatePickerFragment$onCreateDialog$1
│ Leaking: YES (DatePickerDialog↑ is leaking)
│ Anonymous class implementing android.app.DatePickerDialog$OnDateSetListener
│ ↓ DatePickerFragment$onCreateDialog$1.this$0
╰→ god.panchang.DatePickerFragment
Leaking: YES (DatePickerFragment$onCreateDialog$1↑ is leaking and Fragment#mFragmentManager is null and ObjectWatcher was watching this)
key = 6b7d9e5c-79bb-4e74-83c3-c570b34aa23a
watchDurationMillis = 23765
retainedDurationMillis = 18763
, retainedHeapByteSize=1547, pattern=instance field android.os.Message#obj, description=A thread waiting on a blocking queue will leak the last dequeued object as a stack local reference.