ボタンを押すとWebサービスと通信する場合、そのボタンをダブルクリックするとWebサービスが2回呼び出され、二重送信が発生するという問題があります。ボタンが2回目のクリックを受け付けないようにする方法はありますか? この投稿を見ましたが、解決策がうまくいかないようです。
4 に答える
ボタンを無効にするだけでは不十分です。ボタンをクリックできないようにする必要もありますsetClickable(false)
。
setEnabled()
ボタンの外観のみを変更し、引き続きクリック イベントを受け取ります。
私の意見では、Web サービスをいつ実行するかを制御するのが最善の方法です。Web サービス通信のブール値を設定します。このようなもの(疑似コードで。Androidはあまり覚えていません)
private boolean webServiced = false;
public synchronized void startWebService(){
if (!webServiced){
webServiced = true;
//run your web service call on separate thread or something
}
}
public synchronized void onWebServiceDone(){
webServiced = false;
myButton.setClickable(true)
}
public void onButtonClick(Event e){
startWebService();
myButton.setClickable(false)
}
ここで重要なのは、一度に 1 つのスレッドのみが webServiced ブール値にアクセスするように、webService メソッドを同期する必要があることです。これにより、setClickable(false) が開始される前にユーザーがボタンを複数回クリックできたとしても、Web サービスは 1 回だけ実行されます。
これは、イベントが非同期呼び出しであっても、特定のケースや任意のボタンのコード内の他の場所で使用できる一般的なソリューションです。
次に、Web サービス エンドポイントの場合、応答、タイムアウトなどを受け取ったときに、渡されたランナブルを呼び出すと、ボタンがリセットされてもう一度クリック可能になります。以下のクラスを参照してください。
public abstract class OneClickListener implements View.OnClickListener {
private boolean clickable = true;
private Runnable reactivateButtonRunnable;
@Override
public final void onClick(final View v) {
if (clickable) {
clickable = false;
reactivateButtonRunnable = new Runnable() {
@Override
public void run() {
reset();
}
};
onOneClick(v, reactivateButtonRunnable);
}
}
public abstract void onOneClick(View v, final Runnable reactivateButtonRunnable);
// reset listener to accept new clicks
public void reset() {
clickable = true;
}
}
原理を示すための疑似コードの例:
Button button = new Button(this);
button.setOnClickListener(new OneClickListener() {
@Override
public void onOneClick(View v, Runnable reactivateButtonRunnable) {
launchWebService(reactivateButtonRunnable);
}
});
public void launchWebService(final Runnable reactivateButton){
//
doRequest(new OnResponseListener(){
@Override
public void onSuccess(){
// your custom code
reactivateButton.run(); // makes button clickable again here
}
@Override
public void onTimeout(){
// your custom code
reactivateButton.run(); // makes button clickable again here
}
@Override
public void onFailure(){
// your custom code
reactivateButton.run(); // makes button clickable again here
}
});
}
注: これは、Android がボタンのクリック イベントをキューに入れることを妨げるものではありませんが、コードの実行を妨げるものではありません。
ボタンも無効にしたい場合は、Dalmasの回答を参照して、クリック可能な変数が値を変更するこのコードに統合してください....
つまり、クリック時にボタンを無効にしてから、サービス コンシューマー関数/メソッドからのコールバックで再度有効にします。