【问题标题】:Use Isolate to sort list使用 Isolate 对列表进行排序
【发布时间】:2019-10-15 15:11:08
【问题描述】:

我有一个想要排序的非原始列表。

当我对其进行排序时,UI 线程被阻塞并且应用程序冻结了几秒钟。

我试图通过使用 dart 的 Isloate compute 函数来避免这种情况,但由于发送到计算函数的参数必须是基元或基元列表/映射 (send method),所以它不起作用。

总之,有没有办法在不阻塞 UI 线程的情况下执行列表排序(非原始)?

编辑:澄清 - 我试图通过计算调用一个函数,并且我传递了一个对象列表(我从第三方插件获得)作为参数,这些对象具有 Iterable 类型的属性,这导致了一切失败 - 确保所有类型都是原始类型或原始类型列表/映射。根据我收到的答案并将类型从 Iterable 更改为 List ,它起作用了。

【问题讨论】:

  • 使用异步和等待。
  • 你能发布你的排序代码吗?
  • @MangaldeepPannu dart 是异步单线程,所有异步和等待都在同一个线程上运行 + 没有任何异步排序方法。
  • 在排序列表时阻止 UI 几秒钟?你是讲故事的人

标签: flutter dart dart-isolates


【解决方案1】:

我不确定我是否理解您的问题,但您可以像这样对非原始元素列表进行排序:

final List<Element> elements = [
  Element(id: 1),
  Element(id: 7),
  Element(id: 2),
  Element(id: 0)
];

elements.sort((a, b) => a.compareTo(b));
// or
elements.sort((a, b) => a.id > b.id ? 1 : -1);

这将是一个print(elements); 输出:

I/flutter ( 7351): [id: 0, id: 1, id: 2, id: 7]

这就是Element的类

class Element {
  final int id;

  Element({this.id});

  @override
  String toString() => "id: $id";

  int compareTo(Element other) => this.id > other.id ? 1 : -1;
}

编辑:要异步进行,您可以这样做:

Future<List<Element>> asyncSort() async {
  print("before sort: $elements");
  elements = await compute(_sort, elements);
  print("after sort: $elements");
  return elements;
}

static List<Element> _sort(List<Element> list) {
  list.sort((a, b) => a.compareTo(b));
  return list;
}

print("before calling asyncSort(): $elements");
asyncSort();
print("after calling asyncSort(): $elements");

这将是输出:

I/flutter ( 7351): before calling asyncSort(): [id: 1, id: 7, id: 2, id: 0]
I/flutter ( 7351): before sort: [id: 1, id: 7, id: 2, id: 0]
I/flutter ( 7351): after calling asyncSort(): [id: 1, id: 7, id: 2, id: 0]
I/flutter ( 7351): after sort: [id: 0, id: 1, id: 2, id: 7]

Edit2:如果您想向compute 发送一个比较函数,您可以使用MapList 参数与列表和比较函数并传递它列表中,因为compute 只接受一个参数。这是一个例子:

Future<List<Element>> asyncSort() async {
  print("before sort: $elements");
  Map args = {"list": elements, "compare": compare};
  elements = await compute(_sortWith, args);
  print("after sort: $elements");
  return elements;
}

static List<Element> _sortWith(Map args) {
  List<Element> list = args["list"];
  Function(Element a, Element b) compare = args["compare"];

  list.sort((a, b) => compare(a, b));
  return list;
}

static int compare(Element a, Element b) {
  return a.id > b.id ? 1 : -1;
}

【讨论】:

  • 这不是异步的,我说的是在不阻塞 UI 线程的情况下对列表进行排序。如果您正在排序的列表更大,您会注意到应用程序会冻结,直到完成排序。
  • 这可行,但它并不适合我的情况,我有一个具有多个属性的对象列表可供排序(例如:List 可以按姓名、年龄、平均成绩等排序) .我尝试通过发送比较功能来扩展您的解决方案,但无法使其正常工作。有什么方法可以将比较函数传递给计算调用的 _sort 函数?
  • 谢谢!我试图传递一个非静态的比较函数,有点遗憾,你必须为每个比较定义一个静态函数,但它可以工作。
【解决方案2】:

这就是我使用计算的方式,只需将所有参数放到一个列表中,然后在动态对象列表中调用它:

image = await compute(getCropImage, [copyFaces, streamImg]);

imglib.Image getCropImage(List<dynamic> values) {
    var face = values[0]; // copyFaces
    var image = values[1]; // streamImg
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-21
    • 2013-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-13
    相关资源
    最近更新 更多