【问题标题】:Proper way of dismissing DialogFragment while application is in background应用程序在后台时关闭 DialogFragment 的正确方法
【发布时间】:2012-03-08 16:12:02
【问题描述】:

我开始使用 DialogFragment,因为它们可以通过方向变化和其他东西很好地工作。但是我遇到了一个讨厌的问题。

我有 AsyncTask 显示进度 DialogFragment 并关闭它 onPostExecute。一切正常,除非onPostExecute 在应用程序处于后台时发生(例如,在按下主页按钮后)。然后我在 DialogFragment 关闭时收到此错误 - “Can not perform this action after onSaveInstanceState”。多哈。常规对话框工作得很好。但不是 FragmentDialog。

所以我想知道,当应用程序在后台时关闭 DialogFragment 的正确方法是什么?我并没有真正使用过 Fragments,所以我认为我只是错过了一些东西。

【问题讨论】:

  • 另请参阅here,了解使用暂停处理程序的好解决方案

标签: android android-fragments android-dialog android-dialogfragment


【解决方案1】:

DialogFragment 有一个名为dismissAllowingStateLoss() 的方法

【讨论】:

  • 这仅在您使用:show(FragmentManager, tag) 时有效,但在使用 show(FragmentTransaction, tag) 时无效,因为即使我们要求允许状态丢失,dismissInternal 中的 popBackStack 也会调用 enqueueAction(..., allowStateLoss=false)。它在框架和支持版本中都这样做。
【解决方案2】:

这就是我所做的(df == dialogFragment)

确保以这种方式调用对话框:

df.show(getFragmentManager(), "DialogFragment_FLAG");

当您想关闭对话框时,请检查:

if (df.isResumed()){
  df.dismiss();
}
return;

确保片段的 onResume() 方法中包含以下内容(不是 df)

@Override
public void onResume(){
  Fragment f = getFragmentManager().findFragmentByTag("DialogFragment_FLAG");
  if (f != null) {
    DialogFragment df = (DialogFragment) f;
    df.dismiss();
  }
  super.onResume();
}   

这样,如果对话框可见,对话框将被关闭。如果不可见,对话框将在下一个片段变为可见时被关闭(onResume)......

【讨论】:

  • 这总是在用户返回时关闭片段,如果他们还没有阅读对话框,只是在显示后立即离开应用程序怎么办?
  • dismiss() 已经在内部删除了对话框片段。源代码:getFragmentManager().beginTransaction(); ft.remove(this);
【解决方案3】:

这是我必须做的才能实现你想要的: 我有一个片段活动,我在其中显示了一个名为fragment_RedemptionPayment 的对话框片段,该片段在顶部全局声明。如果DialogFragment 在活动进入后台并返回前台之前显示,则以下代码将取消它。

     @Override
        public void onResume() {
            super.onResume();        
            if(fragment_RedemptionPayment.isVisible()){
                fragment_RedemptionPayment.dismiss();
            }
}

【讨论】:

    【解决方案4】:

    在调用dismiss之前检查状态的另一种新方法是:

    if(!dialog.isStateSaved){
        dialog.dismiss()
    } else {
        //Change the UI to suit your functionality
    }
    

    通过这种方式检查状态是否保存,基本上是在暂停和onSaveInstanceState 已被调用。

    对于 Java,您可以使用 isStateSaved()

    【讨论】:

      【解决方案5】:

      一个可行的解决方案是在您的对话片段中设置Fragment.setRetainInstance(true),但这不是最漂亮的修复。

      有时我注意到我必须将我的对话操作排队,让框架首先恢复状态。如果您可以获取当前的 Looper (Activity.getMainLooper()) 并将其包装在 Handler 中,您可以尝试通过在该队列上发布一个可运行对象将您的解雇传递到队列的后面。

      我经常使用一个单独的片段,它有一个retaininstance(true),它有一个ResultReceiver。因此,我将该结果接收器传递给我的工作并在其 onReceive 中处理回调(通常作为其他接收器的路由器)。但是,如果您使用异步任务,这可能比它值得做的工作多一些。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-03-23
        • 2013-07-26
        • 2013-08-05
        • 1970-01-01
        • 2020-10-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多