Android:AsyncTask.doInBackground中的可取消Java Collection排序

时间:2014-08-21 14:41:07

标签: java android collections android-asynctask

我正在为Android手机编写应用程序。

我有一个java.util.ArrayList,其中包含要求自定义java.util.Comparator正确排序的对象。

我知道我可以使用java.util.Collections.sort()但数据量是这样的,我想在ArrayList中对android.os.AsyncTask进行排序。

我不想使用几个AsyncTask对象来对每个数据的子集进行排序。

可以取消任何AsyncTask,因此我希望在排序时定期调用AsyncTask.isCancelled()。如果它返回true,我放弃排序(以及我的整个数据集)。

我用谷歌搜索但无法找到一种AsyncTask友好的排序方式,同时定期检查取消。

我可以在isCancelled()的实现中调用java.util.Comparator.compare(),如果返回true,则抛出我自己的java.lang.RuntimeException子类。然后try{java.util.Collections.sort(ArrayList, Comparator);} catch () {}针对该特定异常。我不会对这种方法感到完全满意。

或者,我可以使用中间java.util.TreeSet并编写2个循环,每个循环在每次迭代之前检查取消。第一个循环会将ArrayList的所有项添加到TreeSet(我的Comparator实现会在插入时对它们进行排序)。由于TreeSet自然ArrayList,第二个循环会将TreeSet中的所有对象以正确的顺序添加回java.util.Iterator。这种方法使用了一些额外的内存,但肯定会有效。

我能想到的最后一种方法是实现我在Android中实际寻找的内容:使用java.util.Listjava.util.Comparator的通用android.os.AsyncTask(最好是快速)排序定期检查取消。

是否有人发现?
你有这个问题的其他解决方案吗?

编辑:

虽然我没有考虑排序方法签名的样子,但我也非常高兴使用android.os.CancellationSignal来决定何时放弃排序。

1 个答案:

答案 0 :(得分:0)

我会试着在这里描述我的思考过程。如果有人在任何时候有更好的报价......

让我们再次肯定我们在这里要实现的目标。 我们需要一个具有以下属性的排序算法

  1. 运行单个任务
  2. 到位,即不使用额外的记忆
  3. 我们应该能够随意取消排序,即当我们决定不再需要它时立即或非常接近它。
  4. 高效
  5. 不会使用异常来控制应用程序的完全正常流程。你对那个人感到不舒服是正确的☺

    没有原生的android工具来做AFAIK

  6. 让我们关注第3项要求。

    以下是asycTask documentation的引用,有关取消任务的部分

      

    块引用   为了确保尽快取消任务,您应该始终从doInBackground(Object [])定期检查isCancelled()的返回值,如果可能的话(例如在循环内)。“

    含义,一种迭代排序算法,在每次迭代时你必须检查isCancalled()标志,这将填补这个要求。问题是简单的迭代排序算法,例如插入排序,通常效率不高。对于小输入而言,这并不重要,但是既然你说你的典型输入是一个巨大的数组列表,并且无论如何都触发了我们的任务,我们需要尽可能保持高效。

    既然你提到了快速排序,我在想,它已经得到了我们需要的一切!这是有效的,它是适当的,它运行在一个单一的任务上。只有一个缺点。它是经典的形式,递归,意味着取消后不会立即返回。幸运的是,一个简短的谷歌搜索产生了许多结果,可以帮助包括this one。简而言之,您可以找到迭代的quicksort变体。这是通过一个堆栈替换递归调用堆栈来完成的,该堆栈存储递归实现将用于预先形成“分区”的相同索引。 拿这个算法,在每次迭代时添加一个检查是否asyncTask.isCancelled(),你就得到了一个满足所有要求的解决方案。