画像の読み込みなどのバックグランドで時間のかかる処理を行っている間、処理が終わる前にUIを動かすことができてしまうとユーザビリティが悪くなってしまいます。今回は、Activitiyで一定時間ユーザの操作を禁止するDialogを生成する方法をご紹介します。
Androidで一定時間操作を止めたいと思ったときの注意点
まず、筆者の失敗例をご紹介します。
「Activityから画像を読み込むTaskを実行していて、画像の読み込みをしている間はユーザが操作できないようにする」
というのが、今回実装したかった機能です。
本来であれば、Taskが完了するまでTask内でProgressDialogを使ってユーザの操作を制御すれば良いのですが、Task内で非同期処理をネストさせて読んでいるため、ProgressDialogでの制御はあまり書きたくありませんでした。
そこで、DialogFragmentを生成して一定時間を指定してThread.sleep()
を使って動きを止めればいいのではと安易な発想をしてしまいました。しかし、Thread.sleep()
を使ってしまうと、Fragment内での動きが止まるだけでなく画像の読み込み(おそらくBackgroud処理は止まっていない?)まで止まってしまいました。考えてみればそりゃそうだと。。
そこで、Threadの処理を止めずに、一定時間経過後に自動で閉じる操作みたいなのを予約する方法は無いかと探してみました。
Handlerを使って一定時間後に指定した処理を実行
Threadの処理を止めずに一定時間後に指定した処理を実行するために、AndroidにはHandlerクラスが用意されています。
こちらを参考に、一定時間経過すると自動で閉じるAlertDialogを作成しました!
完成系はこちら
「Start」ボタンを押すとGameAcitiviyが実行され、LongTaskで画像をバックグランドで取得しています。その間、AlertDialogを生成しており、20秒間ユーザは何もできないようになっています。
public class GameActivity extends AppCompatActivity {
private static final String TAG = GameActivity.class.getSimpleName();
private LongTask mLongTask;
private AlertDialog mDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
// 長いバックグランド処理
mLongTask = new LongTask(this);
mLongTask.execute();
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Please Wait!");
builder.setMessage("Now Loading...");
builder.setCancelable(false);
mDialog = builder.create();
Handler handler = new Handler();
Runnable dialogDismiss = new Runnable() {
public void run() {
mDialog.dismiss();
}
};
mDialog.show();
handler.postDelayed(dialogDismiss, 20000);
}
}
LongTaskが実行されてから20秒間、ユーザがキャンセルできないAlertDialogが表示されます。
まとめ
Handlerを使い、Activityで一定時間経過すると自動で閉じるAlertDialogの作り方をご紹介しました。バックグランド処理の中でさらにバックグランド処理を呼んだりと、ProgressDialogが使いにくいときの回避策としておすすめです。ただし、停止時間を動的に決められないので、処理にかかる時間がバラバラな場合は利用できない点に注意してください。