2016-08-19 5 views
1

У меня есть ObservableCollection, связанный с ListView. Этот список в основном представляет собой набор элементов. Если вы нажмете один, его состояние изменится. Он добавлен в избранное и показан в списке избранных (также ListView) или удален из избранного.Какие шаги можно предпринять для оптимизации ListView

Это основная функция моего приложения, поэтому будет много добавления-удаления. Оба списка медленны, багги и мерцают при обновлении.

Как я могу сделать это быстрее/плавно?

Я попытался запустить все добавления/удаления вызовов рабочего потока. Я попытался использовать функцию Task и async (что сделало ее хуже на самом деле). Есть ли «правильная» реализация этого сценария? (ListView ui thread и рабочая нить, поддерживающая его актуальность) Есть ли статья, которая могла бы научить меня хорошей практике?

Реализация: Примечание: Грузовик - это еще один класс, который хранит данные. Из класса данных:

List<Truck> trucks = new List<Truck>(); 
public void addToFavorites(Truck truck) 
{ 
    foreach(Truck t in trucks) 
    { 
     if(t == truck) 
     { 
      t.setFavorite(true); 
     } 
    } 
} 
public void removeFromFavorites(Truck truck) 
{ 
    foreach (Truck t in trucks) 
    { 
     if (t == truck) 
     { 
      t.setFavorite(true); 
     } 
    } 
} 
public List<Truck> getTrucks() 
{ 
    return trucks; 
} 
public List<Truck> getFavoriteTrucks() 
{ 
    List<Truck> temp = new List<Truck>(); 
    foreach(Truck t in trucks) 
    { 
     if (t.isFavorite()) 
     { 
      temp.Add(t); 
     } 
    } 
    return temp; 
} 

На странице, которая показывает все Грузовики:

public partial class AllPage : ContentPage 
{ 
    public AllPage(csharp.Data data) 
    { 
     //init 
     InitializeComponent(); 
     this.data = data; 
     //build list 
     refreshAsync(); 
     ListView list = new ListView() 
     { 
      ItemTemplate = new DataTemplate(typeof(csharp.PlateCell)), 
      ItemsSource = trucks, 
      IsPullToRefreshEnabled = true, 
     }; 
     //on select 
     list.ItemSelected += (sender, e) => { 
      if (e.SelectedItem == null) return; //row deselected, dont do anything 
      var selection = e.SelectedItem as csharp.Truck; 
      if (selection.isFavorite()) 
      { 
       data.removeFromFavorites(selection); 
       selection.setFavorite(false); 
      } 
      else { 
       data.addToFavorites(selection); 
       selection.setFavorite(true); 
      } 
      ((ListView)sender).SelectedItem = null; // de-select the row 
      refreshAsync(); 
     }; 
     list.RefreshCommand = new Command(() => 
     { 
      //trucks = data.getFavoriteTrucks(); 
      refreshAsync(); 
      list.IsRefreshing = false; 
     }); 
     //add the list to the page 
     root.Children.Add(list); 
    }//end constructor 
    csharp.Data data; 
    ObservableCollection<csharp.Truck> trucks = new ObservableCollection<csharp.Truck>(); 

    private async Task refreshAsync() 
    { 
     await Task.Run(() => refreshThread()); 
    } 

    private void refreshThread() 
    { 
     List<csharp.Truck> all = data.getTrucks(); 
     trucks.Clear(); 
     foreach (csharp.Truck t in all) 
     { 
      trucks.Add(t); 
     } 
    } 
} 
+0

Не могли бы вы добавить код, как вы реализовали _Its добавлен в избранное, и отображается в списке избранного (также ListView) или удаляется из избранного. –

+0

Добавлен класс данных, в котором все хранится и реализация ListView который показывает эти данные. Обратите внимание, что класс Data в будущем будет получать информацию с сервера. Список в настоящее время всегда одинаковый для Data и allPage, когда дело доходит до размера и объектов, которые он содержит, это не всегда так. – wasted

+0

У этого есть все, что нужно - https://developer.xamarin.com/guides/xamarin-forms/user-interface/listview/performance/ –

ответ

4

я думаю, является хорошей отправной точкой, чтобы сообщить себе о Virtualizing

Вы должны избегать обновлению наблюдаемую коллекции в других потоках, чем резьба графического интерфейса пользователя (см. this)

Хорошим моментом было бы иметь Посмотрите на MVVM

Насколько я вижу, вы всегда удаляете свой список и заполняете его снова, вместо того чтобы распространять только изменения. -> Это должно быть ваше внимание, чтобы использовать виртуализацию

также вы можете взглянуть на this. С SmartCollection вы будете запускать событие CollectionChanged только один раз, вместо этого для каждого элемента, который вы добавляете в свой список.

+0

Добавлена ​​реализация, теперь вы будете читать ваши ссылки. Спасибо за ответ! – wasted

+0

Как уже говорилось, может быть больше или меньше объектов каждый раз, когда я обновляюсь. В какой-то момент, когда вы делаете попытку обновления, я должен получить обновленный список из своего класса данных. Кроме того, когда я изменяю поле из объекта грузовиков в моем ObservableCollection, он не обновляет мой список. Я просмотрю ваши ссылки, я уверен, что найду свой ответ. – wasted

+0

Если элемент обновляется внутри наблюдаемого набора, он должен сгенерировать событие PropertyChanged, иначе изменения не будут обновлять пользовательский интерфейс. Хороший подход состоит в том, чтобы все ваши модели просмотра (в данном случае грузовика) наследовались от базового класса ViewModel, который реализует [INotifyPropertyChanged] (https://msdn.microsoft.com/de-de/library/system.componentmodel.inotifypropertychanged (v = vs.110) .aspx). Метод Set вашего свойства должен генерировать свойство PropertyChangedEvent для этого свойства. – Markus

0

Возможно, вы захотите проверить this тему, говорящую о FastCell. Я еще не пробовал его библиотеку, но я планирую, так как у меня также есть список, который очень трясет на Android.

Я слышал, что ограничение количества предметов в вашем списке в любой момент может помочь, но это никогда не делало для меня многого.

Кроме того, ListView теперь позволяет включить ListViewCachingStrategy. RecycleElement, который должен помочь, но похоже, что он не работает в настоящее время, потому что вы меняете содержимое своего ViewCell. Я столкнулся с тем же. Когда включено, iOS, похоже, кэширует ваш первоначальный макет ViewCell, поэтому, когда вы меняете макет ViewCell, пользовательский интерфейс не обновляется. Я знаю, что для этого есть отчет об ошибке, но не уверен, что это за статус.

Кроме того, я бы сделал PlateCell настолько простым, насколько возможно. Чем больше изображений, ярлыков и макетов в вашем ViewCell будет хуже, тем лучше. Вы также можете использовать AbsoluteLayout в своем ViewCell, который, если это будет сделано правильно, может значительно сократить количество необходимых вычислений макета.

Последним шагом, который я еще не хотел сделать, является написать ViewCell в собственном коде, который я слышу гораздо более результативно, чем писать в Xamarin Forms.

Сообщите нам, если что-то придумает для вас!

+1

Внедрение интерфейса INotifyPropertChanged, поскольку Маркус предложил чудеса. Когда я делаю попытку обновить его стопку, хотя я готов согласиться с этим, это всего лишь вторая проблема. Уменьшение количества просмотров списка - это хорошая идея или уменьшение количества элементов другим способом, но позже вы столкнетесь с проблемами. Не каждое устройство имеет одинаковые экраны, и если все элементы списка не масштабируются, вы снова столкнетесь с той же проблемой. Что касается камеры просмотра, вы, вероятно, правы. Установка hasUnevenRows на false помогает также с высокой производительностью. – wasted

+0

@wasted Спасибо за ответ с тем, что сработало для вас. Я уже реализовал это, но я уверен, что это поможет кому-то другому. Если вы найдете больше настроек, дайте мне знать! Еще раз спасибо. – hvaughan3

+0

Rohit прокомментировал выше, я обнаружил, что в статье, опубликованной им, настройка видимости или цвета списка просмотров после создания будет стоить производительности. Проверьте выше, он разместил ссылку с более подробной информацией, которая может быть полезной для вас. – wasted

Смежные вопросы