戌印-INUJIRUSHI- (Androidあれこれ)

Androidのプログラミングをメインにしてます。記事に貼られたソースコードはダブルクリックすることで行番号をはずしてコピーすることができます。

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
08

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Android でのボタン連打制御 (onClick)

作成したアプリのテストでボタンを連打したとき、イベントが2回走ってしまったりすることはありませんか?

例えば、次のアクティビティに遷移するボタン。
クリック時には本来1つのアクティビティしか開かないはずです。
しかし、ボタンを連打することで二重(多重)に開いてしまうことがあります。

これを制御するには以下のような方法があります。

①クリックから一定時間、次のイベントを禁止する
②フラグ管理によりイベントが完了するまで次のイベントを禁止する

とりあえず思いつくのは2つ。他にもあれば教えてください。

①クリックから一定時間、次のイベントを禁止する
// クリックイベント
@Override
public void onClick(View v) {
// 前回クリックから一定時間経過していなければクリックイベントを実行しない
if (!CommonUtils.isClickEvent()) return;

// 次のアクティビティを開く
startActivity(new Intent(this, NextActivity.class));
}

/** クリック連打制御時間(ミリ秒) */
private static final long CLICK_DELAY = 1000;
/** 前回のクリックイベント実行時間 */
private static long mOldClickTime;

/**
* クリックイベントが実行可能か判断する。
* @return クリックイベントの実行可否 (true:可, false:否)
*/
public static boolean isClickEvent() {
// 現在時間を取得する
long time = System.currentTimeMillis();

// 一定時間経過していなければクリックイベント実行不可
if (time - mOldClickTime < CLICK_DELAY) {
return false;
}

// 一定時間経過したらクリックイベント実行可能
mOldClickTime = time;
return true;
}
クリック時に前回クリックイベントを実行してから一定時間経過したかチェックします。
とりあえずの1秒なので禁止時間は各々調整してください。
1秒では短い処理もあるかもしれませんが、長時間の処理は ProgressDialog を表示すると思うので問題ないと思います。

フラグ管理によりイベントが完了するまで次のイベントを禁止する
View#setClickable(false) でクリックを制御する方法もありますが、ボタン等のクリックイベントを持つ View が複数あると制御が面倒になるのでフラグ管理しています。
/** クリックイベント実行可否フラグ */
private boolean mIsClickEvent;

/**
* 再開処理
*/
@Override
protected void onResume() {
super.onResume();

// クリックイベントを許可する
mIsClickEvent = false;
}

/**
* クリックイベント
*/
@Override
public void onClick(View v) {
// クリックイベント実行されていれば実行しない
if (mIsClickEvent) return;

// クリックイベントを禁止する
mIsClickEvent = true;

// 次のアクティビティを開く
startActivity(new Intent(this, NextActivity.class));
}
onClick が実行されたタイミングでクリックイベントを禁止します。
しかし、このままだと次のアクティビティから戻ったときにクリックできないままとなってしまいます。
そこでライフサイクルで必ず実行される onResume の中でフラグを元に戻します。

なぜこのような実装が必要なのか?

Android では UI の処理は全てメインスレッド(UI スレッド) で行われます。
ここで注意するのは、メインスレッドはボタンがクリックされた等のイベントをすぐに処理するわけではないということです。
イベントは一度メッセージキューに登録され、メインスレッドはこのメッセージキューからイベントを取り出して実行します。
この登録から実行までにはほんのわずかの間があるため、メインスレッドがイベントを実行する前にメッセージキューに複数のイベントが登録されてしまうことがあります。

そのため処理側で今回の①②のような対応が必要になります。
スポンサーサイト

Comments

Leave a Comment


Body
プロフィール

とむ・やむくん

Author:とむ・やむくん
管理人について

Windows 7 / 64bit
Eclipse 4.2 Juno (日本語パッチ済)

スポンサーサイト
最新トラックバック
検索フォーム
ブロとも申請フォーム
QRコード
QR
Twitter
2013/01/04 19:00 カウント開始

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。