L
L
Lordao2019-04-14 19:33:26
Android
Lordao, 2019-04-14 19:33:26

How to fix memory leak when displaying DialogFragment?

Fragments are displayed in the following way:
Activity - NavigationFragment - TestFragment
When TestFragmentthe button is pressed, it is displayed DialogFragmentwith 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()
    }
}

SelectListDialog
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)
        }
    }
}

5cb360aa5117a851399043.png

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Denis Zagaevsky, 2019-04-14
@Lordao

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 question

Ask a Question

731 491 924 answers to any question