[英]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
...這是延遲時間短嗎?
- 當我多次單擊 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;
}
偽代碼:
...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();
}
偽代碼:
// 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.