Вопрос по windows-phone-8, windows-runtime, windows-phone, c# – Источник изображения и кеширование

11

Я использую следующий код для отображения изображений с веб-сервера:

   

Изображение загружается автоматически, и я предполагаю, что есть также некоторое кэширование на основе URL.

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

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

Ваш Ответ

5   ответов
1

(сохранить изображение из Интернета в локальном хранилище и привязать сохраненное изображение к странице)

XAML

<listview itemssource="{Binding Items}">
<listview.itemtemplate>
    <datatemplate>
        <!--Some code removed-->
        <img source="{Binding Img_Thumb.Result}">
    </datatemplate>
</listview.itemtemplate>
</listview>

Модель данных

public class DataModel_ListOfEvents
{
    public DataModel_ListOfEvents(String img_thumb)
    {
        this.Img_Thumb = new NotifyTaskCompletion<string>(JsonCached.ImageFromCache2(img_thumb));
    }
    public NotifyTaskCompletion<string> Img_Thumb { get; private set; }
}

public sealed class SampleData_ListOfEvents
{
    private static SampleData_ListOfEvents _sampleDataSource = new SampleData_ListOfEvents();

    private ObservableCollection<datamodel_listofevents> _items = new ObservableCollection<datamodel_listofevents>();
    public ObservableCollection<datamodel_listofevents> Items { get { return this._items; } }
}
</datamodel_listofevents></datamodel_listofevents></datamodel_listofevents></string></string>

магия

publi,c class JsonCached
{
    public static async Task<string> ImageFromCache2(string path)
    {
        int ru = path.IndexOf(".ru") + 4;// TODO: .com .net .org
        string new_path = path.Substring(ru).Replace("/", "\\");

        StorageFolder localFolder = ApplicationData.Current.LocalFolder;
        try
        {
            Stream p = await localFolder.OpenStreamForReadAsync(new_path);
            p.Dispose();
            System.Diagnostics.Debug.WriteLine("From cache");
            return localFolder.Path + "\\" + new_path;
        }
        catch (FileNotFoundException)
        {

        }
        catch (Exception e)
        {
            System.Diagnostics.Debug.WriteLine("{0}", e.Message);
        }

        StorageFile storageFile = await localFolder.CreateFileAsync(new_path, CreationCollisionOption.OpenIfExists);

        Uri Website = new Uri(path);
        HttpClient http = new HttpClient();
        // TODO: Check connection. Return message on fail.
        System.Diagnostics.Debug.WriteLine("Downloading started");
        byte[] image_from_web_as_bytes = await http.GetByteArrayAsync(Website);

        MakeFolders(localFolder, path.Substring(ru));

        Stream outputStream = await storageFile.OpenStreamForWriteAsync();
        outputStream.Write(image_from_web_as_bytes, 0, image_from_web_as_bytes.Length);
        outputStream.Position = 0;

        System.Diagnostics.Debug.WriteLine("Write file done {0}", outputStream.Length);

        outputStream.Dispose();
        return localFolder.Path + "\\" + new_path;
    }

    private static async void MakeFolders(StorageFolder localFolder, string path)
    {
        //pics/thumbnail/050/197/50197442.jpg
        int slash = path.IndexOf("/");
        if (slash <= 0) // -1 Not found
            return;

        string new_path = path.Substring(0, slash);
        StorageFolder opened_folder = await localFolder.CreateFolderAsync(new_path, CreationCollisionOption.OpenIfExists);
        string very_new_path = path.Remove(0, new_path.Length + 1);
        MakeFolders(opened_folder, very_new_path);
    }
}
</string>

NotifyTaskCompletion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;

namespace App2.NotifyTask
{
    public sealed class NotifyTaskCompletion<tresult> : INotifyPropertyChanged
    {
        public NotifyTaskCompletion(Task<tresult> task)
        {
            Task = task;
            if (!task.IsCompleted)
            {
                var _ = WatchTaskAsync(task);
            }
        }
        private async Task WatchTaskAsync(Task task)
        {
            try
            {
                await task;
            }
            catch
            {
            }
            var propertyChanged = PropertyChanged;
            if (propertyChanged == null)
                return;
            propertyChanged(this, new PropertyChangedEventArgs("Status"));
            propertyChanged(this, new PropertyChangedEventArgs("IsCompleted"));
            propertyChanged(this, new PropertyChangedEventArgs("IsNotCompleted"));
            if (task.IsCanceled)
            {
                propertyChanged(this, new PropertyChangedEventArgs("IsCanceled"));
            }
            else if (task.IsFaulted)
            {
                propertyChanged(this, new PropertyChangedEventArgs("IsFaulted"));
                propertyChanged(this, new PropertyChangedEventArgs("Exception"));
                propertyChanged(this,
                  new PropertyChangedEventArgs("InnerException"));
                propertyChanged(this, new PropertyChangedEventArgs("ErrorMessage"));
            }
            else
            {
                propertyChanged(this,
                  new PropertyChangedEventArgs("IsSuccessfullyCompleted"));
                propertyChanged(this, new PropertyChangedEventArgs("Result"));
            }
        }
        public Task<tresult> Task { get; private set; }
        public TResult Result { get { return (Task.Status == TaskStatus.RanToCompletion) ? Task.Result : default(TResult); } }
        public TaskStatus Status { get { return Task.Status; } }
        public bool IsCompleted { get { return Task.IsCompleted; } }
        public bool IsNotCompleted { get { return !Task.IsCompleted; } }
        public bool IsSuccessfullyCompleted { get { return Task.Status == TaskStatus.RanToCompletion; } }
        public bool IsCanceled { get { return Task.IsCanceled; } }
        public bool IsFaulted { get { return Task.IsFaulted; } }
        public AggregateException Exception { get { return Task.Exception; } }
        public Exception InnerException { get { return (Exception == null) ? null : Exception.InnerException; } }
        public string ErrorMessage { get { return (InnerException == null) ? null : InnerException.Message; } }
        public event PropertyChangedEventHandler PropertyChanged;
    }
}
</tresult></tresult></tresult>
1

https://github.com/molinch/FFImageLoading/)

ХарактеристикиПоддержка Xamarin.iOS (мин. IOS 7), Xamarin.Android (мин. Android 4), Xamarin.Forms и Windows (WinRT, UWP)Настраиваемое кеширование дисков и памятиДедупликация похожих запросов на загрузку / загрузкуОшибка и загрузка поддержки заполнителейИзображения могут быть автоматически уменьшены до указанного размера (меньше использования памяти)Поддержка WebPЗагрузка изображений Поддержка Fade-In анимацииМожно повторить загрузку изображений (RetryCount, RetryDelay)В Android прозрачность отключена по умолчанию (настраивается). Экономит 50% памятиПоддержка преобразованийBlurredTransformationКругТрансформация, ОкруглыйПреобразование, УглыТрансформацияColorSpaceTransformation, GrayscaleTransformation, SepiaTransformationFlipTransformationПоддержка пользовательских преобразований (реализация платформы ITransformation на собственной платформе)

Это'так же просто, как:

<ff:mvxcachedimage name="image" verticalalignment="Stretch" horizontalalignment="Stretch" loadingplaceholder="loading.png" errorplaceholder="error.png" retrycount="3" retrydelay="250" downsampleheight="300" imagepath="http://lorempixel.com/output/city-q-c-600-600-5.jpg">

</ff:mvxcachedimage>

Примеры проектов здесь:https://github.com/molinch/FFImageLoading/tree/master/samples/

линияCacheDuration="30" имеет тот же эффект, что и делатьCacheDuration = TimeSpan.FromDays(30) в C #, верно? Enrique Zavaleta
FFImage теперь устарел, вы должны использоватьMvxCachedImageView, Я'уточню мой ответ. Работает на всех платформах. Вы должны установитьCacheDuration свойство, которое имеетTimestamp тип. Daniel Luberda
Привет спасибо за отличный образец Я использую привязку для вставки изображения в загрузку ffimage в Android. Если я установлю длительность кэша на определенное время для этого ffimage, это нормально работает? Deepak
1

что для этого есть какая-то сборка, но вы можете сохранить изображения в IsolatedStorage и использовать конвертер, который проверяет доступность Интернета и возвращает либо онлайн, либо офлайн URL-адрес.

Быстрый поиск дал это что может быть именно то, что вы ищете (этосовместим с Windows Phone 7 и может быть не лучшим решением для Windows Phone 8)

спасибо, я уже видел эту ссылку, я действительно думал, что такая базовая функция будет встроена в элемент управления ... thumbmunkeys
23

BitmapImage автоматически кэширует удаленные изображения по умолчанию. Это'лучше всего использовать в сочетании сCreateOptions="BackgroundCreation" для лучшей производительности.

<img height="100" width="100" margin="12,0,9,0">
  <image.    <bitmapimage urisource="{Binding ImgURL}" createoptions="BackgroundCreation">
  </bitmapimage></image.

Это сообщение в блоге MSDN, старый, но все еще актуальный, перечисляет и объясняет всеCreationOptions и что кэширование происходит автоматически в большинстве режимов.

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

Ручной подход

Если ты'Я хотел бы контролировать кеширование самостоятельно и кэшировать HTTPS-ресурсы, тогда есть несколько хороших примеров ...

ImgCache из приложения iFixitКонвертер значений, который загружает и сохраняет изображенияPersistentImageCache из набора инструментов Kawagoe (может потребоваться обновление для работы с WP 7.5 или 8)
Ссылки делают этот ответ идеальным :) Вот некоторые дополнения:github.com/artem-zinnatullin/jet-image-loader Alex Sorokoletov
тот'Возможно, это наследие Silverlight - т.е. дон»t кешировать содержимое HTTPS в браузере. Если вы хотите кэшировать ресурс HTTPS, вы 'Я должен написать это сам - я могу добавить пару ссылок на несколько хороших примеров, если хотите? Neil Turner
спасибо, этот блог великолепен! Я понял, что http-адреса кэшируются, а https - по каким-либо причинам. У тебя есть идея почему? thumbmunkeys
этот аргумент Silverlight звучит очень разумно, и что касается примеров, да, мне нравится :) thumbmunkeys
4

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

Может использоваться как конвертер связывания, такВы не должны даже менять свой код! Просто обновите свои XAML!

Пожалуйста, проверьтеобразцы в хранилище, вы'буду любить это;)

Особенности:

Кеширование на дискеКеширование в памятиПолностью асинхронныйДоступен как конвертер связывания или программно из вашего кодаПолностью с открытым исходным кодом, форк и улучшить его!

Вот пример:

<img source="{Binding ImageUrl, Converter={StaticResource MyAppJetImageLoaderConverter}}">
Что вы имеете в виду с "герметичном»? Утечки памяти? Если это так, кэш-память на основеWeakRefDictionary, такGC может собирать объекты, когда хочет, без утечек памяти :) Вы можете написать мне на GitHub, если у вас есть вопросы Artem Zinnatullin
Я полагаю, это проблема wp7. Я не тестировал wp8 :) Vitalii Vasylenko
Эй, хорошо выглядишь. Изображения также оказались не протекающими? Vitalii Vasylenko
В любом случае, спасибо за этот вопрос, япопробую проверить это в ближайшее время Artem Zinnatullin

Похожие вопросы