Android 防止多次执行异步任务
我在单击按钮时从UI线程调用asynctask,该按钮执行一些HTTP Get请求Android 防止多次执行异步任务,android,android-asynctask,Android,Android Asynctask,我在单击按钮时从UI线程调用asynctask,该按钮执行一些HTTP Get请求 如果用户在当前任务完成之前再次单击按钮,会发生什么情况?这是由asynctask内部处理的,还是我需要自己处理?您可以在asynctask上调用getStatus()来检查它是否已经运行,在这种情况下单击“忽略”按钮 要做到这一点,您必须将AsyncTask的一个实例保存到某个地方并访问它。有两种方法 1:显示进度对话框并阻止用户进一步输入 2:在类作用域私有中创建AsyncTask变量。然后,此任务将不会运行超
如果用户在当前任务完成之前再次单击按钮,会发生什么情况?这是由asynctask内部处理的,还是我需要自己处理?您可以在
asynctask
上调用getStatus()
来检查它是否已经运行,在这种情况下单击“忽略”按钮
要做到这一点,您必须将
AsyncTask
的一个实例保存到某个地方并访问它。有两种方法
1:显示进度对话框并阻止用户进一步输入
2:在类作用域私有中创建AsyncTask变量。然后,此任务将不会运行超过一次。另一个异步任务将生成,这可能会给您带来困难-保存数据时的竞争条件(如果您正在持久化数据),等等。我建议在接收
onClick
事件时禁用按钮,并显示一个说明如下的微调器:后台正在发生一些事情
我们在操作栏中放置了一个刷新按钮,实现了类似的功能。请注意,我们的异步任务在app.Service
下运行,因此在配置更改期间(其中hasStartedSync
获取重新初始化),我们依赖于“isTheSyncServiceRunning”检查
两种方式:
onPreExeccute()
中,显示一个带有setCancelable(false)
的ProgressDialog。在AsyncTask调用的onPostExecute()
的OnProgressDialog()中。这将显示一个阻塞进度对话框。您也可以在此处显示一些消息或进度
onPreExeccute()
中,调用setEnabled(false)
on按钮。在AsyncTask调用的onPostExecute()
中setEnabled(true)
on按钮。这将在任务运行时禁用该按钮。也可以在这些点更改按钮文本。甚至可以临时用进度微调器(如ActionBar中的)替换它onDoInBackground()
中的所有内容包装在一个try catch
中,以便AsyncTask始终正常退出,并且始终调用onPostExecute()
。您可以从onPostExecute(result)
的result参数判断HTTP请求是否得到了任何东西
示例:只需调用此方法,单击一些按钮,即可从服务器将一些文本加载到TextView
:
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();
}
publicstaticvoidrunhttp(最终文本视图targetView,最终按钮triggerBtn){
//---新任务----
AsyncTask任务=新建AsyncTask(){
@凌驾
受保护的void onPreExecute(){
super.onPreExecute();
//----禁用按钮---
triggerBtn.setEnabled(false);
//---显示消息----
setText(“加载…”);
}
@凌驾
受保护的void onPostExecute(字符串结果){
super.onPostExecute(结果);
//----更新结果---
targetView.setText(结果);
//----重新启用按钮---
triggerBtn.setEnabled(真);
}
@凌驾
受保护的字符串背景(无效…无效){
//---默认值--
String result=“无数据”;
//--为了安全--
试一试{
//-----在这里做耗时的事情---
}捕获(例外e){
//---误差值--
result=“获取数据时出错”;
}
返回结果;
}
};
//----运行任务----
task.execute();
}
为什么不使用布尔标志并检查其状态?我在我的永无止境的清单中使用了这种逻辑,它从未失败过
在doInBackground()中切换标志
然后再次在onPostExecute()
对于按钮的“单击侦听器”
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
}
}
});
asynctask的实例不能执行多次。@njzk2但每次单击按钮都会创建一个新实例。然后由您决定。我建议在单击时停用该按钮,并仅在asynctask完成时(最有可能在onPostExecute中)重新激活该按钮。您也可以只有一个asynctask实例。好的,但是如果它已经在运行,而我再次按下它,会发生什么呢?它似乎没有抛出任何异常。你可以为每个按钮或类似的东西保留一个异步任务,如果它已经在运行,只需忽略按钮单击。我明白了。关于您的第二个选项:我是否应该在我的onCreate'方法上设置asynctask,并在我的按钮中设置它?@Johan如果这样做,您将无法再次运行它。有一个asynctask成员,因此您可以检查其状态,如果它已完成,您可以创建一个新的asynctask并分配给同一成员。是的,您可以这样做。并检查已经运行的异常。强制用户查看进度对话框是一个坏主意(您在google+或gmail应用程序中看到进度对话框了吗?)。。。用户应该能够在等待数据时执行其他操作(如关闭应用程序、更改设置…@lenik您有关于如何“拥有asynctask成员”的示例吗?thanksprogress对话框糟透了。。。你在google+或gmail应用程序中看到进度对话框了吗。。。更好的模式是将不确定的进度放在某个地方,并禁用不需要的UI(如此按钮),所以-1表示对话框,+1表示禁用button@Selvin选项是一个选项:)。此外,谷歌还创建了ProgressDialog
,这样至少在某些情况下会有一些用处。@Selvin就像当你的手机关机时,他们不能冒险让你
@Override
protected Void doInBackground(Void... params) {
loadingData = true;
}
@Override
protected void onPostExecute(Void result) {
// CHANGE THE LOADINGMORE STATUS TO PERMIT FETCHING MORE DATA
loadingData = false;
}
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
}
}
});