簡體   English   中英

如何抑制多次按鈕點擊?

[英]How suppress multiple button clicks?

我想知道在 Xamarin.Forms 上處理 http 請求的最佳方法。

現在我以這種方式處理請求:

首先,我的表單上有一個按鈕,如下所示:

btn_1.Clicked += (sender, e) => {
    Confirm(name, password);
};

我的Confirm()函數檢查主菜並拋出請求事件。 它也在請求事件完成后執行邏輯。 例如:

private async void Confirm(string name, string password) {
    UserController user_controller = new UserController();
    if (name != null && password != null) {
        User user = new User(name, password);
        bool ok = user_controller.Login(user);
        if(ok){
            Navigation.InsertPageBefore(new NextPage(), this);
            await Navigation.PopAsync();
        } else {
            //Show error code...
        }
    }
}

我的UserController對每個 http 請求都有兩個函數。 第一個執行請求。 第二個調用第一個並處理答案。

1º:

private async Task<HttpResponseMessage> user_login(User user){
    try {
        Uri uri = new Uri("http://localhost/user/login");
        string user_json = JsonConvert.SerializeObject(user);
        StringContent content = new StringContent(user_json, Encoding.UTF8, "application/json");
        return await Utilities.client.PostAsync(uri, content).ConfigureAwait(false);
    } catch {
        return null;
    }
}

2º:

public bool Login(User user) {
    http_response = user_login(user).GetAwaiter().GetResult();
    //If it doesn't reach the server...
    if (http_response != null) {
        //Depending of the status of the response
        switch (http_response.StatusCode) {
            case (System.Net.HttpStatusCode)200:
                 try {
                    string content = http_response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
                    Response response = JsonConvert.DeserializeObject<Response>(content);
                    return (bool) response.aux;
                  } catch {

                  }
                  break;
            case (System.Net.HttpStatusCode)401:
                 ...
                 break;
            default:
                 ...
                 break;
        }
    } else {
        App.Current.MainPage.DisplayAlert("Error", "No server connection", "OK");
    }
    return false;
}

這完成了我對每個請求的協議。 我的問題是:

1.我不確定這是否是正確的方法

2.當我多次點擊btn_1它會多次拋出請求

我該怎么做才能避免這種情況? 我試圖鎖定我的按鈕,但它不起作用。 我在異步請求方面遇到了很多麻煩。 我不知道哪種處理請求的最佳方式是一次只拋出一個請求

編輯:

我創建了這個按鈕擴展:

public partial class LockableButton: Button {
    public event EventHandler ThrowEvent;
    public bool ShowLoading { get; set; }

    public LockableSimpleButton() {
        ShowLoading=false;

        InitializeComponent();

        this.Clicked += async (object sender,EventArgs e) => {
            if (!Utilities.Unlocked) { return; }
            Utilities.Unlocked=false;
            try {
                if (ShowLoading) {
                    await Navigation.PushModalAsync(new LoadingPopUp());
                    ThrowEvent(sender,e);
                    await Navigation.PopModalAsync();
                } else {
                    ThrowEvent(sender,e);
                }
            } finally {
                await Task.Delay(1000); 
                Utilities.Unlocked=true;
            }
        };
    }
}

現在我的按鈕是這樣的:

   btn_1.ThrowEvent += async (sender, e) => {
        Navigation.InsertPageBefore(new Page(),this);
        await Navigation.PopAsync(false);
   };

錯誤仍然存​​在是怎么回事?

當我多次單擊該按鈕時,它會引發錯誤,因為它試圖在同一頁面上多次使用PopAsyc ...這是延遲時間短嗎?

  1. 當我多次單擊 btn_1 時,它會多次拋出請求

此問題與處理異步 HTTP 請求無關。

這里有兩種經典的編碼技術,用於丟棄額外的按鈕按下。

它們是設置標志並丟棄設置該標志時發生的任何點擊的變體。

常見偽代碼:

static bool _busy;

...click handler... {
    if (_busy) return;

    _busy = true;
    // Special code as needed.

    ... handle the click ...

    // This code must always be executed.
    // If it isn't, the button action will never occur again.
    _busy = false;
}
  1. 處理完第一次點擊后,啟動一次性計時器。 在該計時器觸發之前,放棄任何額外的點擊。

偽代碼:

...click handler... {
    if (_busy) return;

    _busy = true;
    try {
        ... handle the click ...
    } finally {
        var timer = new Timer(TimerTick, 250 milliseconds, one-time);
        timer.Start();
    }
}

void TimerTick() {
    // This code must always be executed.
    // If it isn't, the button action will never occur again.
    _busy = false;
    //maybe timer.Stop();
}
  1. 當您開始處理第一次點擊時,設置一個標志。 完成處理后清除該標志。 丟棄在設置該標志時發生的任何點擊。

偽代碼:

// Must be `async` method, so events continue while processing.
// Otherwise, the second button press might simply be on hold,
// until after this finishes, so doesn't get suppressed.
...click handler... {
    if (_busy) return;

    _busy = true;
    try {
        ... handle the click ...
    } finally {
        // This code must always be executed.
        // If it isn't, the button action will never occur again.
        _busy = false;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM