从onRequestPermissionsResult()中调用DialogFragment的show()会在Marshmallow中导致IllegalStateException

and*_*dev 38 android android-fragments android-dialogfragment android-permissions android-6.0-marshmallow

脚步:

  1. Fragment或请求许可Activity
  2. 从内部显示DialogFragment onRequestPermissionsResult()
  3. java.lang.IllegalStateException 抛出:之后无法执行此操作 onSaveInstanceState

当我在延迟一段时间后显示对话框时(使用postDelayed),这不会发生.据http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html)上,我们可以蜂窝后设备commit()之间onPause()onStop()没有任何国家损失或异常.这是一个示例项目源,日志文件和记录问题的链接. https://drive.google.com/folderview?id=0BwvvuYbQTUl6STVSZF9TX2VUeHM&usp=sharing

此外,我已经打开了一个问题https://code.google.com/p/android/issues/detail?id=190966,但它被标记为WorkingAsIntended,他们建议只捕获异常.但这并没有解决问题.我知道解决它的其他方法,但这不是这个安卓漏洞吗?

更新 错误状态再次"分配".希望很快就能解决.我的临时解决方案是

new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        // do your fragment transaction here
    }
}, 200);
Run Code Online (Sandbox Code Playgroud)

Ken*_*eth 24

错误被接受并将被修复,但是,我强烈反对postDelayed和计时器解决方案.执行此操作的最佳方法是在Activity中引入状态标志,您可以在其中设置回调,并使用onResume或类似的.例如:

private boolean someFlag;

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
// some code checking status
    someFlag = true;
}
Run Code Online (Sandbox Code Playgroud)

然后在onResume:

protected void onResume() {
    if(someFlag == true) {
        doSomething();
        someFlag = false;
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 6

我也认为这是android bug.我无法相信他们将您的问题标记为WorkingAsIntended.目前唯一的解决方案是延迟执行代码,onRequestPermissionsResult()直到android人员正确修复此问题.

如果有人想知道如何延迟执行,这是我解决这个问题的方法:

  @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {

    if (requestCode == PERMISSION_CODE) {
      if (/* PERMISSION ALLOWED/DENIED */) {
          new Timer().schedule(new TimerTask() {
              @Override public void run() {
                  // EXECUTE ACTIONS (LIKE FRAGMENT TRANSACTION ETC.)
              }
          }, 0);
      }
  }

这基本上会延迟执行直到onRequestPermissionsResult()完成,所以我们没有得到java.lang.IllegalStateException.这适用于我的应用程序.


小智 4

尝试这样的事情:

// ...
private Runnable mRunnable;

@Override
public void onResume() {
   super.onResume();

   if (mRunnable != null) {
       mRunnable.run();
       mRunnable = null;
   }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
   super.onRequestPermissionsResult(requestCode, permissions, grantResults);

   if (/* PERMISSION_DENIED */) {
      mRunnable = /* new Runnable which show dialogFragment*/;
   }
}
Run Code Online (Sandbox Code Playgroud)