【Android】ダイアログの表示でメモリリーク

2019年7月29日

ダイアログを表示して、画面の向きを変えるとメモリリークが発生した話し。
ボタンを押したらダイアログを表示する場合、下記のようなコードを書いていました。
よく見かけるコードで本などでも、こんなコードだった。

//ボタンのクリックイベントでダイアログ表示
public void BtnClick(View v) {
	new AlertDialog.Builder(this)
		.setIcon(android.R.drawable.ic_dialog_alert)
		.setTitle("ダメな例")
		.setMessage("ダイアログのテストです")
		.setPositiveButton("OK",
			new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog,
					int whichButton) {
				}
			}).show();
}

ボタンも表示されるし、これでずっと大丈夫だと思っていましたが、
画面を横向きにすると「LogCat」にエラーが表示される!!
ずっと気が付きませんでした、、、
こんなエラーがたくさん出た。

08-25 16:11:10.995: ERROR/WindowManager(13041): Activity com.test.TestDialog.TestDialog1 ・・・・
08-25 16:11:10.995: ERROR/WindowManager(13041)


画面が回転した際に、メモリリークが発生したみたいです。
色々調べてみると、下記のようにすればエラー(メモリリーク)が発生しないみたいです。

//ボタンのクリックイベントで「showDialog」を呼び出す
public void Click(View v) {
	showDialog(0);
}
@Override
protected Dialog onCreateDialog(int id) {
	Dialog dialog = super.onCreateDialog(id);
	// idは複数のダイアログを使用する場合に使用する
	if (id == 0) {
		AlertDialog.Builder builder= new AlertDialog.Builder(this);
		builder.setIcon(android.R.drawable.ic_dialog_alert);
		builder.setTitle("これならエラーが出ない");
		builder.setMessage("ダイアログのテストです");
		builder.setPositiveButton("OK",
			new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog,
					int whichButton) {
				}
			}); //ここで.showしない
		//.createを使う
		AlertDialog alert = builder.create();
	}
	return dialog;
}
@Override
protected void onPrepareDialog(int id, Dialog dialog) {
	super.onPrepareDialog(id, dialog);
	if (id == 0) {
		//ダイアログの内容に変更がある場合に記述
	}
}

これで、エラーがなくなりました。

※追記(その他の対処方法)
AlertDialogで「.show()」を使用する場合でも、「AndroidManifest」のactivityタグプロパティに
android:configChanges="orientation" 」を設定することでメモリリークが起きなくなった。
この設定項目は「画面回転時にアクティビティの破棄/再生成を行わない」 ということらしい。

スポンサーリンク