Бесконечная прокрутка WP8 LongListSelector с изображениями

1

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

Я использую xaml, который выглядит так:

<Image Stretch="UniformToFill" 
      Margin="-3,0,0,0" 
      Source="{Binding video_thumbnail}" 
      Opacity="1" 
      Height="200" Width="480" />

video_thumbnail - это строка.

Должен ли я создавать изображение таким образом или есть лучший способ оптимизировать мой код?

  • 0
    да, в определенный момент у вас может быть исключение нехватки памяти. Я не могу понять вашу проблему, у вас есть проблемы с отображением бесконечного LongListSelector или вы ищете лучшие практики в отображении изображений
  • 0
    нет, бесконечный LongListSelector работает - просто похоже, что при загрузке изображений после прокрутки он запрашивает новые данные и загружает эти изображения очень медленно - поэтому я просто хотел узнать, использовал ли я наилучшую практику для нескольких изображений для сценарий бесконечной прокрутки
Показать ещё 2 комментария
Теги:
xaml
windows-phone-8

2 ответа

3
Лучший ответ

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

Вы можете подумать, что изображения будут загружаться медленнее, но это не так. Загрузка 5 изображений по одному занимает одинаковое количество времени при одновременном загрузке всех 5. Я тестировал его в своем приложении.

Вот мой пример. Во-первых, я создал класс для хранения основной информации о видео: url для миниатюры и самого миниатюры как ImageSource, поэтому вы можете легко привязать его к свойству Source Image в XAML.

public class VideoItem
{
    public string Url { get; private set; }
    public ImageSource Thumbnail { get; set; }

    public VideoItem(string url)
    {
        this.Url = url;
    }
}

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

public class VideoLibrary
{
    private WebClient thumbnailDownloader = new WebClient();
    private Queue<VideoItem> downloadQueue = new Queue<VideoItem>();
    private bool isBusy = false;

    public ObservableCollection<VideoItem> Videos = new ObservableCollection<VideoItem>();

    public VideoLibrary()
    {
        thumbnailDownloader.OpenReadCompleted += OnThumbnailDownloaded;
    }

    // It will not start downloading process but only add a new video item (without thumbnail) to download queue.
    public void Download(string url)
    {
        downloadQueue.Enqueue(new VideoItem(url)); // Just add to queue.
        CheckQueue();
    }

    // Check whether there are new thumbnails to download. If so, start downloading just one.
    private void CheckQueue()
    {
        if (isBusy) // Stop! Downloading in progress...
            return;

        if (downloadQueue.Count > 0)
        {
            isBusy = true;
            VideoItem item = downloadQueue.Peek();
            thumbnailDownloader.OpenReadAsync(new Uri(item.Url));
        }
    }

    // One thumbnail has been downloaded. We can add it to the list of videos and check the queue again.
    private void OnThumbnailDownloaded(object sender, OpenReadCompletedEventArgs e)
    {
        isBusy = false;

        if (e.Cancelled)
        {
            CheckQueue(); // Just try again.
        }
        else if (e.Error != null)
        {
            downloadQueue.Dequeue(); // Skip this video (thumbnail), check the next one.
            CheckQueue();
        }
        else if (downloadQueue.Count > 0)
        {
            VideoItem item = downloadQueue.Dequeue(); // Remove the video from queue.
            WriteableBitmap bitmap = new WriteableBitmap(null); 
            bitmap.SetSource(e.Result);
            item.Thumbnail = bitmap; // Thumbnail is ready to use.

            Videos.Add(item); // Add to list.

            CheckQueue();
        }
    }
}
  • 0
    Я должен загрузить все картинки в изолированное хранилище? Это длинный список предметов, которые могут технически расти вечно ...
  • 0
    Нет, я имею в виду только локальный список картинок. Я покажу вам мой пример, когда я отредактирую этот ответ.
2

Согласно этой статье:

  • Никогда не связывайте размещенные на сервере изображения непосредственно с элементом управления, поскольку среда выполнения Silverlight будет использовать поток пользовательского интерфейса (с помощью WebClient) для извлечения этого изображения с сервера, что может сделать пользовательский интерфейс неактивным в течение некоторого времени.

  • Используйте фоновый поток и реализацию класса на основе HttpWebRequest, чтобы загрузить данные изображения эффективным способом, который в конечном итоге создает BitmapImage и устанавливает это как источник. Чистая обертка MVVM вокруг этого упростит управление вашим изображением.

Кроме того, перейдите по ссылке "Лучшие практики для разработки Windows Phone ",

  • установите значение BitMapCredtiOptions для BackGroundCreation. Это позволит использовать кешированное изображение, если оно уже существует для UriSource.

  • Если изображение имеет большой размер, например изображение с высоким разрешением, захваченное многими телефонными камерами, то при декодировании всех пикселей изображения может быть использовано значительное количество обработки ЦП. Если вам известен размер кадра изображения, который вы собираетесь отображать, вы можете использовать эту информацию, чтобы установить размер пикселя для декодирования.

  <Image ..>
    <Image.Source> 
         <BitmapImage
             UriSource="{Binding video_thumbnail}"
             CreateOptions="BackgroundCreation"/> 
   </Image.Source> 
 </Image>

Ещё вопросы

Сообщество Overcoder
Наверх
Меню