Используйте Isolate для сортировки списка - PullRequest
0 голосов
/ 15 октября 2019

У меня есть непримитивный список, который я хотел бы отсортировать.

Когда я сортирую его, поток пользовательского интерфейса блокируется, и приложение останавливается на несколько секунд.

Я пыталсячтобы избежать этого с помощью функции dart Isloate compute , но поскольку параметр, отправляемый в функцию compute, должен быть примитивом или списком / картой примитивов ( метод отправки ), он не работал.

В заключение, есть ли способ выполнить сортировку списка (не примитивную) без блокировки потока пользовательского интерфейса?

Редактировать: Уточнение - я пытался вызвать функцию с помощью compute иЯ передавал список объектов (который я получил от стороннего плагина) в качестве аргумента, у этих объектов было свойство типа Iterable, и это вызывало сбой всего - убедитесь, что все типы являются примитивными или List / Map примитивов. С полученными ответами и изменением типа с Iterable на List это сработало.

Ответы [ 2 ]

2 голосов
/ 15 октября 2019

Я не уверен, что понял ваш вопрос, но вы можете отсортировать список не примитивных элементов следующим образом:

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;
}
1 голос
/ 16 октября 2019

Вот как я использую вычисления, просто помещаю все параметры в список, а затем вызываю его в списке динамического объекта:

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

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