2015-10-04 147 views
0

场景:Asynctask和队列OR延迟执行

用户有一个项目列表,比方说10个项目。每个项目都有一个操作按钮,它调用一个可以进行Web通话的AsyncTask。当调用时,该项目任务的执行过程中会显示一个微调

问题:

一些用户的滥用这一点,并快速按下多个操作按钮,quicklt此起彼伏,执行网络电话太频繁。所以我希望能够以某种方式,在执行之间延迟2秒执行每个AsyncTasks。如果可能的话,我不想从AsyncTask切换到别的东西。因此,基本上,如果有按下3的操作按钮时,执行应该是:

- >操作1 - > 2秒延时 - >操作2 - > 2秒延时 - >操作3 - > .. ..

在Android中这样做的最好方法是什么?

LE:

我刚刚意识到的东西,用于执行我的任务我跑到下面的代码:

myTask = new MyTask(); 
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
    myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
} else { 
    myTask.execute(); 
} 

嗯,我已经使用了很多的时间这个代码现在,知道在蜂窝之后,如果不使用Executor,任务不会并行执行。所以看起来只需要做一个简单的myTask.execute()并添加一个Thread.sleep()就可以让我的AsyncTasks按照预期一个接一个地执行。

回答

1

您需要维护一个需要执行的操作列表。 单击按钮添加列表中的任务,调用一个方法,检查任务列表并执行它,如果没有其他任务正在运行..

在onPostExecute方法调用相同的方法来检查是否有其他任务/操作需要执行..

它可能不是你所需要的完整代码...但可以给你一些想法..

public class TestActivity extends AppCompatActivity { 

    private static boolean isTaskRunning =false; 
    static ArrayList<CustomTask> customTaskList = new ArrayList(); 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_test); 
    } 

    public void onBtnClick(View view) 
    { 
     // create custom task with required values and actions 
     CustomTask customTask = new CustomTask(); 
     customTaskList.add(customTask);   

     checkAndExecuteTask(); 
    } 


    private static void checkAndExecuteTask() 
    { 
     //checks if there is any task in the list and is there any other   running task 
     if(customTaskList.size()>0 && !isTaskRunning) { 
      new MyAsync(customTaskList.get(0)).execute(); 
     } 
    } 

    static class MyAsync extends AsyncTask<Void,Void,Void> 
    { 
     CustomTask currentCustomTask; 

     public MyAsync(CustomTask customTask) 
     { 
      currentCustomTask = customTask; 
     } 

     @Override 
     protected void onPreExecute() { 
      super.onPreExecute(); 
      isTaskRunning= true; 
     } 

     @Override 
     protected Void doInBackground(Void... voids) { 

      // do your stuff 
      return null; 
     } 

     @Override 
     protected void onPostExecute(Void aVoid) { 
      super.onPostExecute(aVoid); 
      customTaskList.remove(currentCustomTask); 
      isTaskRunning =false; 
      checkAndExecuteTask(); // task is completed so check for another  task and execute (if any). 
     } 
    } 

    class CustomTask 
    { 
     // create class with required fields and method 
    } 
} 
+0

也许我失去了一些东西,但如果我按接连3个的操作按键之一,在过去2个项目将在几乎同时进行,因为有将是最后2个线程的睡眠时间为2秒,几毫秒让我按下按钮... – Alin

+0

如何使用进度对话框?当任务正在运行时显示它..当进度对话框在屏幕上可见时..用户将无法触及其他操作按钮...当任务完成时..关闭onPostExecute方法中的对话..这样将只有一个任务将运行.. – Tarun

+0

另一种选择是维护需要执行的操作的列表....在点击按钮上添加动作到列表..并调用一个方法来检查是否已经有一个正在运行的任务。它没有任何运行..它执行数组列表中的操作.....在后执行方法从数组列表中删除操作..并调用相同的方法来检查是否有任何其他操作需要被执行.... – Tarun

1

有许多的你可以在android中做到这一点。 一种方法是使用handler

你需要做的是,创建一个单独的线程并在其中运行handler.postDelayed。

private void startWebCall() { 

    Thread thread = new Thread() { 
     public void run() { 
      Looper.prepare(); 

      final Handler handler = new Handler(); 
      handler.postDelayed(new Runnable() { 
       @Override 
       public void run() { 
        // Do your web calls here 
        handler.removeCallbacks(this); 
        Looper.myLooper().quit(); 
       } 
      }, 2000); 

      Looper.loop(); 
     } 
    }; 
    thread.start(); 
} 

无论何时用户单击某个项目,都应该调用上述方法。

,我能想到的另一种方法是使用IntentService

的IntentService是用于在后台执行异步任务的服务。它维护着它需要做的任务的队列。与上述方法不同的是,它按顺序执行这些任务。因此,当您向网络电话发出请求时,它会将它们排队,进行第一个呼叫,然后在完成后它将进行第二个呼叫。所以不同的网络电话将不会并行执行。它们将按顺序执行,但执行的是另一个线程。它也是一种服务,所以它可以在后台运行,即用户关闭应用程序。

This是一个很好的教程,以开始使用IntentService。

应该避免使用AsyncTaks,除非需要做的工作非常简单。 This博客解释了它的陷阱。

+0

谢谢你的回答,它确实看起来像它做我需要的东西,但我想使用现有的AsyncTask实现。目前不需要IntentService,因为操作很简单,并且需要不断更新接口。 – Alin

0

该算法将做按您的要求:

ButtonA.onclick() { 
    final Handler handler = new Handler(); 
    handler.postDelayed(new Runnable() { 
     @Override public void run() { 
      MytaskA.execute(); 
     } 
    }, 2000); 
} 

ButtonB.onclick() { 
    final Handler handler = new Handler(); 
    handler.postDelayed(new Runnable() { 
     @Override public void run() { 
      MytaskB.execute(); 
     } 
    }, 2000); 

} 
ButtonC.onclick() { 
    final Handler handler = new Handler(); 
    handler.postDelayed(new Runnable() { 
     @Override public void run() { 
      MytaskC.execute(); 
     } 
    }, 2000); 

}