Answer the question
In order to leave comments, you need to log in
How to fix memory leak when displaying DialogFragment?
Fragments are displayed in the following way:
Activity - NavigationFragment - TestFragment
When TestFragment
the button is pressed, it is displayed DialogFragment
with checkboxes. At this point, a memory leak occurs.
How can memory leaks be fixed?
Test Fragment
package com.example.test.fragments
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import kotlinx.android.synthetic.main.layout_first.*
import com.example.test.R
class TestFragment : Fragment() {
private var multiDialogFragment: SelectListDialog? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? = inflater.inflate(R.layout.layout_first, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
button.setOnClickListener {
if (multiDialogFragment == null) {
multiDialogFragment = SelectListDialog.newInstance(arrayListOf("1", "2", "3"))
multiDialogFragment?.setTargetFragment(this, SelectListDialog.REQUEST_CODE)
}
multiDialogFragment?.show(requireFragmentManager(), TAG)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == SelectListDialog.REQUEST_CODE) {
val list = data?.extras?.getStringArrayList(SelectListDialog.LIST)?.toMutableList()
?: arrayListOf()
Log.d("result", list.toString())
}
}
override fun onDestroyView() {
button.setOnClickListener(null)
multiDialogFragment?.dismiss()
super.onDestroyView()
}
companion object {
const val TAG = "Fragment"
fun newInstance() = TestFragment()
}
}
package com.example.test
import android.app.AlertDialog
import android.app.Dialog
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.DialogFragment
import org.jetbrains.anko.bundleOf
class SelectListDialog : DialogFragment() {
private var list: ArrayList<String> = arrayListOf()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments.let {
list = it?.getStringArrayList(LIST) as ArrayList<String>
}
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val selectedItems = ArrayList<String>()
val builder = AlertDialog.Builder(targetFragment?.activity)
builder.setTitle("List of strings")
.setMultiChoiceItems(list.toTypedArray(), null) { _, which, isChecked ->
if (isChecked) {
selectedItems.add(list[which])
} else if (selectedItems.contains(list[which])) {
selectedItems.remove(list[which])
}
}
.setPositiveButton("Okay") { dialog, _ ->
val intent = Intent().putExtra(LIST, selectedItems)
targetFragment?.onActivityResult(targetRequestCode, REQUEST_CODE, intent)
dialog.dismiss()
}
.setNegativeButton("Cancel") { dialog, _ ->
dialog.dismiss()
}
return builder.create()
}
companion object {
const val LIST = "list"
const val REQUEST_CODE = 134
fun newInstance(list: ArrayList<String>) = SelectListDialog().apply {
arguments = bundleOf(LIST to list)
}
}
}
Answer the question
In order to leave comments, you need to log in
Do not save this dialog in the field of another fragment, and if you do, nullify the link to it when it is no longer needed.
What kind of perversions with onActivityResult? Make your own interface, implement it in target, and cast to it, pull the desired method. What for once again through intent to transfer the data if it is possible directly.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question