tyb
tyb

Reputation: 4749

Refresh fragment when dialogfragment is dismissed

Is there any way I can detect when a DialogFragment is dismissed, so that i can update its parent fragment?

Upvotes: 22

Views: 22235

Answers (7)

Iman Dolatkia
Iman Dolatkia

Reputation: 226

As @Luke mentioned, the top answer has issues. You can also achieve what you want with FragmentLifecycleCallbacks without any custom interfaces or listeners.

1- Create a inner FragmentLifecycleCallbacks () class:

    // Create a FragmentLifecycleCallbacks (inner) class:
    inner class ChildFragmentCallbacks : FragmentManager.FragmentLifecycleCallbacks() {
         override fun onFragmentPaused(fm: FragmentManager, f: Fragment) {
            super.onFragmentPaused(fm, f)
            if(f is YourDialogFragment){
                // YourDialogFragment is closed, you can update parent fragment here
                updateParentFragment()
            }
        }
    }

2- Register it on onCreate():

childFragmentManager.registerFragmentLifecycleCallbacks(ChildFragmentCallbacks(), false)

total code:

import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager

class YourParentFragment : Fragment() {

    // ...

    // Create a FragmentLifecycleCallbacks (inner) class:
    inner class ChildFragmentCallbacks : FragmentManager.FragmentLifecycleCallbacks() {
         override fun onFragmentPaused(fm: FragmentManager, f: Fragment) {
            super.onFragmentPaused(fm, f)
            if(f is YourDialogFragment){
                // YourDialogFragment is closed, you can update parent fragment here
                updateParentFragment()
            }
        }
    }

    private fun updateParentFragment(){
      // Do it  
    }

    // Register it on onCreate():
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        childFragmentManager.registerFragmentLifecycleCallbacks(ChildFragmentCallbacks(), false)
    }

    // ...

}

Upvotes: 0

Luke Needham
Luke Needham

Reputation: 3989

The top rated answers here have issues.

You cannot hold listeners as instance variables in a DialogFragment, as they will not survive recreation, and you will left wondering why your callbacks 'magically' stop working.

You can read more about this here:

https://medium.com/@lukeneedham/listeners-in-dialogfragments-be636bd7f480

This article offers a couple of real solutions, of which my favourite is to use targetFragment with a custom interface. For intercepting the dismiss, that looks like:

class MainFragment : Fragment(R.layout.fragment_main), DummyDialogCallback {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        openDialogButton.setOnClickListener {
            val dialog = DummyDialog()
            dialog.setTargetFragment(this, DIALOG_DUMMY)
            dialog.show(requireFragmentManager(), "DummyDialog")
        }
    }

    override fun onDummyDialogClick() {
        Toast.makeText(requireContext(), "Dummy click", Toast.LENGTH_SHORT).show()
    }

    companion object {
        const val DIALOG_DUMMY = 1
    }
}

class DummyDialog : DialogFragment() {
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ) = inflater.inflate(R.layout.dialog_dummy, container, false)

    override fun onDismiss(dialog: DialogInterface) {
        super.onDismiss(dialog)
        val callback = targetFragment as? DummyDialogCallback
        callback?.onDummyDialogClick()
    }
}

interface DummyDialogCallback {
    fun onDummyDialogClick()
}

Upvotes: 0

NOT_A_PROGRAMMER
NOT_A_PROGRAMMER

Reputation: 1924

I tried @Gazer answer, it doesn't work for me, I am using different fragment class

import android.app.Fragment; 

But I got this working

  1. Create an interface class

    public interface MyDialogListener {
        void OnCloseDialog(Object obj); //you can put any object here
    }
    
  2. Implement the interface class in the Parent Fragment

    public class ActionBarFragment extends Fragment implements MyDialogListener{
    
        @Override
        public void OnCloseDialog(Object obj) {
            //Do you refresh
        }
    
  3. and then I add the listener inside the DialogFragment

    public class SpecialDialogFragment extends DialogFragment { 
    
        MyDialogListener mListener;
    
        public SpecialDialogFragment(MyDialogListener listener) {
            this.mListener = listener;
        }
    
        @Override
        public void onStop() {
            super.onStop();
            if(mListener!=null)
               mListener.OnCloseDialog(null);
        }
    

Upvotes: 2

Ricardo Markiewicz
Ricardo Markiewicz

Reputation: 977

You can add a listener and override the onDismiss of your fragment dialog :

public class DismissDialog extends DialogFragment {
    private DialogInterface.OnDismissListener onDismissListener;

    public void setOnDismissListener(DialogInterface.OnDismissListener onDismissListener) {
        this.onDismissListener = onDismissListener;
    }

    @Override
    public void onDismiss(DialogInterface dialog) {
        super.onDismiss(dialog);
        if (onDismissListener != null) {
            onDismissListener.onDismiss(dialog);
        }
   }
}

Then, on the parent, you set a listener :

DismissDialog d = new DismissDialog();
d.setOnDismissListener(new DialogInterface.OnDismissListener() {
        @Override
        public void onDismiss(DialogInterface dialog) {

        }
    });
d.show(getSupportFragmentManager(), "sometag");

Upvotes: 37

Sundraw
Sundraw

Reputation: 227

I just solved this in my project. What I have is an activity with a ListFragment. In that list fragment, when a particular item is clicked, I display a DatePickerFragment (a custom DialogFragment that displays a DatePickerDialog). When a date is selected, I want the ListFragment to be refreshed.

To achieve this, in the activity that hosts the ListFragment (and it also hosts the DatePickerFragment, as a matter of fact) I implemented a method that simply replaces the ListFragment with a new instance, like so:

public void criteriaChanged()
{
    getFragmentManager().beginTransaction()
            .replace(R.id.container, new FilterFragment())
            .commit();
}

I call this method from the DatePickerFragment, from onDateSet():

FilterActivity fa = (FilterActivity) getActivity();
fa.criteriaChanged();

This does the trick for me.

Upvotes: 0

Jarrod
Jarrod

Reputation: 151

One way to deal with this is to embed your DialogFragment within an Activity and display the activity as a Dialog, there's a tip in the following link that explains how:

http://developer.android.com/guide/topics/ui/dialogs.html

You can use this to update the underlying Fragment because when the Dialog (which is an Activity) is finished, onResume() will be called on the underlying fragment. Add code to update the state of the fragment in the onResume() method and that's all there is too it.

Upvotes: 1

cottonBallPaws
cottonBallPaws

Reputation: 21600

Override onDismiss() of DialogFragment, or when building the underlying dialog, set a listener with setOnDimissListener().

Upvotes: 3

Related Questions