DialogFragment.dismissAllowingStateLoss

FragmentTransaction.commitAllowingStateLossで、バックグラウンドに置いておく前にFragmentの状態を保存しておいて、その間に非同期処理などを経てFragment状態変更をしてしまうと例外が発生がしてしまうことがあった。
DialogFragmentにおいても、バックグラウンドに置いておいた状態で、非同期処理後にダイアログ閉じようとすると、例外が起きる。
DialogFragment.dismissAllowingStateLossで、それを抑止できる。

DialogFragment  |  Android Developers

CustomAsyncTask.javaで、

package com.bgstation0.android.sample.dialogfragment_;

import android.content.Context;
import android.os.AsyncTask;
import android.widget.Toast;

public class CustomAsyncTask extends AsyncTask<Integer, Integer, String> {	// 非同期処理に渡すパラメータがInteger, 進捗状態がInteger, 非同期処理の結果がStringのCustomAsyncTask.

	// メンバフィールドの定義
	Context context;	// Context型context
	CustomDialogFragment cdf;	// CustomDialogFragment型cdf
	
	// コンストラクタ
	public CustomAsyncTask(Context context){
		this.context = context;	// this.contextメンバに格納.
	}
	
	// コンストラクタ(フラグメントも受け取る.)
	public CustomAsyncTask(Context context, CustomDialogFragment cdf){
		this(context);
		this.cdf = cdf;	// this.cdfメンバに格納.
	}

	// 非同期処理
	@Override
	protected String doInBackground(Integer... params){
		// オブジェクトの宣言
		String ret = "";	// 戻り値の文字列retに""をセット.
		// tryで囲む.
		try{
			Thread.sleep(10000);	// 10秒休止
			if (params.length > 0){	// paramsの要素数が1つでもある.
				ret = "params[0] = " + params[0];	// retに0番目の引数.
			}
			else{
				ret = "params[0] = nothing";	// retにnothing.
			}
		}
		catch (Exception ex){
			ret = "excaption";	// retにexception.
		}
		return ret;
	}

	// UIスレッドの更新
	@Override
	protected void onPostExecute(String result){
		// cdfの非表示.
		try{
			cdf.dismiss();	// cdf.dismissdで非表示.
			Toast.makeText(context, "cdf.dismiss() success!", Toast.LENGTH_LONG).show();	// "cdf.dismiss() success!"とToast表示.
		}
		catch (Exception ex){
			Toast.makeText(context, ex.toString(), Toast.LENGTH_LONG).show();	// ex.toString()をToast表示.
		}
	}
	
}

まず、そのままdismissでやると、

起動時
起動時

起動時。
Button1押して、

ダイアログ表示
ダイアログ表示

ダイアログ表示。
ここのButton1押して、

10秒後にダイアログ閉じて非表示成功
10秒後にダイアログ閉じて非表示成功

10秒後にダイアログ閉じて非表示成功。
これはいいんだけど、次の場合について考える。

ダイアログ表示中にButton1押す
ダイアログ表示中にButton1押す

ダイアログ表示中にButton1押す。
そして、10秒経たないうちに素早くホームボタンを押す。

10秒経つと例外が出てしまう
10秒経つと例外が出てしまう

10秒経つと例外が出てしまう。

横にしてDialogFragmentを起動する
横にしてDialogFragmentを起動する

横にしてDialogFragmentを起動する。

閉じられていない状態になっちゃってる
閉じられていない状態になっちゃってる

閉じられていない状態になっちゃってる。

ちなみに回転しないで復帰すると閉じられている
ちなみに回転しないで復帰すると閉じられている

ちなみに回転しないで復帰すると閉じられている。

cdf.dismissAllowingStateLossにすると、

例外は起きない
例外は起きない

例外は起きない。
ただ、回転して復帰だとダイアログ表示状態、回転しないと非表示で、ここは変わってなかった。
まあ、tryを囲まずに例外が起きないってことかな。

Sample/android/DialogFragment/dismissAllowingStateLoss/src/DialogFragment at master · bg1bgst333/Sample · GitHub