我正在单击一个按钮从我的 UI 线程调用一个异步任务,该按钮执行一些 HTTP-Get 请求。
如果用户在当前任务完成之前再次单击按钮会发生什么?这是由 asynctask 在内部处理的,还是我需要自己处理?
我正在单击一个按钮从我的 UI 线程调用一个异步任务,该按钮执行一些 HTTP-Get 请求。
如果用户在当前任务完成之前再次单击按钮会发生什么?这是由 asynctask 在内部处理的,还是我需要自己处理?
有两种方法可以做到这一点。
1:显示进度对话框并阻止用户进一步输入。
2:在私有类范围内创建 AsyncTask 变量。那么这将永远不会运行超过一次。
为什么不使用布尔标志并检查它的状态?我在我的永无止境的列表中使用了这个逻辑,它从来没有失败过。
切换标志doInBackground()
@Override
protected Void doInBackground(Void... params) {
loadingData = true;
}
然后又在onPostExecute()
@Override
protected void onPostExecute(Void result) {
// CHANGE THE LOADINGMORE STATUS TO PERMIT FETCHING MORE DATA
loadingData = false;
}
而对于 Button 的点击监听器
your_btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (loadingData == false) {
// RUN THE ASYNCTASK AGAIN
} else if (loadingData == true) {
// SHOW A TOAST THAT YOU ARE ALREADY FETCHING DATA
}
}
});
您可以要求getStatus()
您AsyncTask
检查它是否已经在运行并在这种情况下忽略按钮单击。
为此,您绝对需要保存AsyncTask
某处的实例并可以访问它。
将产生另一个 AsyncTask,这可能会给您带来困难 - 如果您要持久保存数据,则会出现竞争条件等。我建议在接收onClick
事件时禁用按钮并显示一些描述的微调器,表明在背景。
我们通过放置在操作栏中的刷新按钮实现了类似的效果。请注意,我们的异步任务app.Service
在配置更改期间运行(hasStartedSync
重新初始化),我们依赖“isTheSyncServiceRunning”检查。
// on setting the selection buttons up
public void onPrepareOptionsMenu(final Menu menu) {
super.onPrepareOptionsMenu(menu);
final MenuItem refreshItem = menu.findItem(id.sync);
if (isSynchronisationServiceRunning() || hasStartedSync) {
refreshItem.setEnabled(false);
if (Build.VERSION.SDK_INT > 10) {
// Replace the refresh icon with an indeterminate spinner for > 10 API.
final LayoutInflater inflater = (LayoutInflater)getSherlockActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
refreshItem.setActionView(inflater.inflate(layout.actionbar_indeterminate_progress, null));
}
} else {
refreshItem.setEnabled(true);
refreshItem.setActionView(null);
}
}
// on selection.
public boolean onOptionsItemSelected(final MenuItem item) {
boolean isSelected;
switch (item.getItemId()) {
case id.sync:
// Fire request to start GET here.
hasStartedSync = true;
invalidateOptionsMenu();
break;
...
两种方式:
在onPreExeccute()
AsyncTask 中显示一个 ProgressDialog 及其setCancelable(false)
. 在ProgressDialog 上onPostExecute()
的 AsyncTask 调用中。dismiss()
这将显示一个阻止进度对话框。您还可以在此处显示一些消息或进度。
在onPreExeccute()
AsyncTask 中,调用setEnabled(false)
Button。在Button 上onPostExecute()
的 AsyncTask 调用中。setEnabled(true)
只要任务正在运行,这将禁用该按钮。您还可以在这些点更改按钮文本。或者甚至暂时用进度微调器替换它(如在 ActionBar 中)。
此外,您可以在“运行”和“取消”行为之间切换按钮,就像现代 Web 浏览器中的刷新按钮一样。这将为用户提供更多控制权。
注意事项:将所有内容包装onDoInBackground()
在 a 中try-catch
,以便 AsyncTask 始终正常退出,并onPostExecute()
始终被调用。可以通过 result 参数onPostExecute(result)
判断 HTTP 请求是否得到任何东西。
示例:只需调用此方法即可TextView
在单击 some 时将一些文本加载到从服务器中Button
:
public static void runHTTP(final TextView targetView, final Button triggerBtn){
//---new task----
AsyncTask<Void,Void,String> task = new AsyncTask<Void, Void, String>(){
@Override
protected void onPreExecute() {
super.onPreExecute();
//----disable button---
triggerBtn.setEnabled(false);
//---show message----
targetView.setText("Loading...");
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
//----update result---
targetView.setText(result);
//----re-enable button---
triggerBtn.setEnabled(true);
}
@Override
protected String doInBackground(Void... voids) {
//---default value--
String result = "No Data";
//--for safety--
try{
//-----do time consuming stuff here ---
}catch (Exception e){
//---error value--
result = "Error fetching data";
}
return result;
}
};
//----run task----
task.execute();
}