【问题标题】:Asynctask and queue OR delay in execution异步任务和队列或执行延迟
【发布时间】:2015-10-04 20:57:52
【问题描述】:

场景:

用户有一个项目列表,比如说 10 个项目。每个项目都有一个操作按钮,它调用一个进行网络调用的 AsyncTask。进行调用时,项目会在任务执行期间显示一个微调器

问题:

有些用户滥用这个,快速按下更多操作按钮,一个接一个,执行网络调用过于频繁。所以我希望能够以某种方式一个接一个地执行每个 AsyncTask,执行之间有 2 秒的延迟。如果可能的话,我不想从 AsyncTask 切换到其他东西。所以基本上如果按下了3个操作按钮,执行应该是:

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

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

乐:

我刚刚意识到一些事情,为了执行我的任务,我运行了以下代码:

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 像预期的那样一个接一个地执行。

【问题讨论】:

    标签: android android-asynctask queue


    【解决方案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
        }
    }
    

    【讨论】:

    • 可能我遗漏了什么,但是如果我一个接一个地按下 3 个操作按钮,最后 2 个几乎会同时执行,因为最后会有 2 秒的线程休眠2 个用了几毫秒的时间让我按下了按钮......
    • 使用进度对话框怎么样?在任务运行时显示它..当屏幕上显示进度对话框时..用户将无法触摸其他操作按钮...当任务完成时..在 onPostExecute 方法中关闭对话框..这样将只有一项任务正在运行..
    • 另一种选择是维护需要执行的操作列表....单击按钮将操作添加到列表中..并调用一个方法来检查是否已经存在运行任务。它没有任务正在运行..它执行数组列表中的操作.....在后执行方法上从数组列表中删除操作..并调用相同的方法来检查是否有任何其他操作需要被执行……
    • 谢谢您的回答在我测试过的情况下有效。但我意识到了一些事情,我已经编辑了我的问题。你怎么看?
    【解决方案2】:

    您可以通过多种方式在 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 博客解释了它的陷阱。

    【讨论】:

    • 感谢您的回答,它确实看起来像我需要的那样,但我想使用现有的 AsyncTask 实现。暂时不需要IntentService,因为操作简单,界面需要不断更新。
    猜你喜欢
    • 2011-05-19
    • 2012-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多