当DialogFragment关闭时刷新片段。

22

有没有办法检测当DialogFragment被关闭时,我可以更新它的父Fragment?

7个回答

37

您可以添加一个监听器并覆盖您的片段对话框的onDismiss:

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

然后,在父组件上设置一个监听器:

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

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

这是一个糟糕的解决方案,因为您的listener将无法在重新创建后继续工作,并且您的回调将会“神奇地”停止工作。这里详细解释了此问题: https://medium.com/@lukeneedham/listeners-in-dialogfragments-be636bd7f480请参见此处以获取更好的解决方案: https://dev59.com/a2kw5IYBdhLWcg3wfKrZ#64479938 - Luke Needham
1
我同意@Luke的观点,这个答案已经很老了(5年了),现在我们有更好的工具和解决方案来解决这个问题。 - Ricardo Markiewicz

3

18
这句话的意思是,“这告知了‘DialogFragment’已被解除,但并未告知其父Fragment,而问题正是关于父Fragment的。” - howettl
父级可以使用这些方法来获取回调并在其关闭时做出响应。有关用法,请参见此答案:https://dev59.com/a2kw5IYBdhLWcg3wfKrZ#29518363 - cottonBallPaws

2
我尝试了@Gazer的解答,但对我没有用,因为我正在使用不同的片段类。
import android.app.Fragment; 

但我已经解决了这个问题。
  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);
        }
    

1

解决这个问题的一种方法是将您的DialogFragment嵌入到一个Activity中,并将该Activity显示为对话框,以下链接中有一个提示来解释如何实现:

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

你可以使用这个方法来更新底层的Fragment,因为当Dialog(它是一个Activity)完成时,底层的fragment将会调用onResume()。在onResume()方法中添加代码来更新fragment的状态就可以了。保留HTML标签。

我认为这是最好的方法,但是API 8+怎么办?这是在API 11中添加的。 - Iree

0
我刚在我的项目中解决了这个问题。我有一个带有ListFragment的活动。在那个列表片段中,当单击特定项目时,我显示一个DatePickerFragment(一个自定义DialogFragment,用于显示DatePickerDialog)。选择日期后,我希望ListFragment被刷新。
为了实现这一点,在托管ListFragment的活动中(实际上它也托管了DatePickerFragment),我实现了一个方法,简单地用新实例替换ListFragment,如下所示:
public void criteriaChanged()
{
    getFragmentManager().beginTransaction()
            .replace(R.id.container, new FilterFragment())
            .commit();
}

我从DatePickerFragment的onDateSet()方法调用此方法:

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

这对我来说很管用。


0

这里的最佳答案存在问题。

DialogFragment中,你不能将监听器保存为实例变量,因为它们不会幸存于重建过程中,你会惊奇地发现你的回调 '神奇地' 停止工作。

你可以在这里阅读更多相关信息:

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

本文提供了几个实际的解决方案,其中我最喜欢的是使用带有自定义接口的targetFragment。要拦截dismiss,可以这样做:
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()
}

0
如@Luke所提到的,最佳答案存在问题。你也可以通过使用FragmentLifecycleCallbacks来实现你想要的功能,而无需使用任何自定义接口或监听器。
1- 创建一个内部的FragmentLifecycleCallbacks()类:
    // 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- 在onCreate()方法中注册它:
childFragmentManager.registerFragmentLifecycleCallbacks(ChildFragmentCallbacks(), false)

总代码:
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)
    }

    // ...

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接