防止asynctask多次执行

时间:2012-11-27 08:49:53

标签: android android-asynctask

我在点击按钮时从我的UI线程调用asynctask,它执行一些HTTP-Get请求。

如果用户在当前任务完成之前再次单击该按钮会发生什么?这是由asynctask在内部处理,还是我需要自己处理它?<​​/ p>

5 个答案:

答案 0 :(得分:6)

有两种方法可以做到这一点。

1:显示进度对话框并阻止用户进一步输入。

2:在类范围private中创建AsyncTask变量。然后这将永远不会运行一次。

答案 1 :(得分:4)

为什么不使用布尔标志并检查它的状态?我在永无止境的列表中使用了这个逻辑,它从未失败过。

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
        }
    }
});

答案 2 :(得分:2)

您可以在getStatus()上致电AsyncTask以检查它是否已在运行,并在这种情况下忽略按钮点击。

要做到这一点,你绝对需要在某处保存AsyncTask的实例并且可以访问它。

答案 3 :(得分:1)

另一个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;
   ...

答案 4 :(得分:1)

两种方式:

  1. 在AsyncTask的onPreExeccute()中显示一个ProgressDialog及其setCancelable(false)。在onPostExecute()的AsyncTask中,在ProgressDialog上调用dismiss()。这将显示阻止进度对话框。您还可以在此处显示一些消息或进度。

  2. 在AsyncTask的onPreExeccute()中,在Button上调用setEnabled(false)。在onPostExecute()的AsyncTask中,在Button上调用setEnabled(true)。只要任务正在运行,这将禁用该按钮。您还可以在这些点更改按钮文本。或者甚至用进度微调器暂时替换它(比如在ActionBar中)。

  3. 此外,您可以在“运行”和“取消”行为之间切换按钮,就像现代Web浏览器中的刷新按钮一样。这将为用户提供更多控制。

    注意事项:将onDoInBackground()内的所有内容包裹在try-catch中,以便AsyncTask始终正常退出,并始终调用onPostExecute()。您可以从onPostExecute(result)的结果参数判断HTTP请求是否有任何结果。

    示例:只需点击一些TextView,即可调用此方法将一些文本从服务器加载到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();
    }