1

我有一个非原始列表,我想对其进行排序。

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

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

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

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

4

2 回答 2

2

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

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,你可以使用一个Map或一个List参数与列表和比较函数并传递它而不是列表,因为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;
}
于 2019-10-15T19:14:52.880 回答
1

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

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

imglib.Image getCropImage(List<dynamic> values) {
    var face = values[0]; // copyFaces
    var image = values[1]; // streamImg
}
于 2019-10-16T02:05:31.670 回答