Что такое glidex.forms?
Библиотека glidex.forms
- это Xamarin.Forms
реализация Glide, который является одним из квазистандартов для обработки изображений на Android (даже рекомендован Google). К счастью, Джонатан Пепперс из Microsoft стремится улучшить Xamarin.Android
, и Xamarin.Forms
также извлекает из этого большое преимущество. Он сделал Xamarin.Android
библиотеку привязки, а также реализацию Xamarin.Forms
. Как и раньше с Xamarin.Forms.Nuke, я узнал об этой библиотеке, потому что заменяю свое прежнее решение для кэширования изображений на Akavache.
Зачем нужно расширять библиотеку?
Если вы хотите загрузить заполнитель, который хранится в ресурсах вашего Android-проекта - в этом нет необходимости. Вы можете просто реализовать собственный хук в GlideExtensions
класс glidex.forms
(я вам тоже покажу). Но если вы хотите загрузить изображение из Xamarin.Forms
ресурса или даже из шрифта, нам нужно немного расширить класс GlideExtensions
.
Кстати, я попытался использовать существующий механизм реализации IGlideHandler
для этих целей, но из-за проблем с синхронизацией мне так и не удалось загрузить такие заполнители, и я пошел дальше, расширив класс GlideExtensions
.
Покажи мне код!
Используйте ресурс Android
Давайте сначала посмотрим, как загрузить ресурс Android в качестве заполнителя (потому что это самый простой способ). Для этого нам просто нужно создать собственную реализацию IGlideHandler
в проекте Android, который затем будет вызываться реализацией GlideExtensions
:
public class GlideWithAndroidResourcePlaceholder : IGlideHandler { public GlideWithAndroidResourcePlaceholder() { } public bool Build(ImageView imageView, ImageSource source, RequestBuilder builder, CancellationToken token) { if (builder != null) { //easiest way - add the image to Android resources .... //general placeholder: //builder.Placeholder(Resource.Drawable.MSicc_Logo_Base_Blue_1024px_pad25).Into(imageView); //error placeholder: builder.Error(Resource.Drawable.MSicc_Logo_Base_Blue_1024px_pad25).Into(imageView); return true; } else return false; } }
Как видите, в RequestBuilder
уже есть механизм заполнителя. Мы просто подключаемся к этому. Если вам нужен общий заполнитель (изображение отображается также во время загрузки), используйте метод Placeholder
. Только при неудачной загрузке изображения используйте Error
method. Вот и все.
Используйте Xamarin.Forms resouce / FontImageSource
Однако, поскольку мы хотим иметь возможность загружать ресурсы FontImageSource
и Xamarin.Forms
, нам нужно пойти другим путем. Как и в случае с iOS, нам нужно добавить свойство-заполнитель в класс Forms
:
public static ImageSource? PlaceholderImageSource { get; private set; }
Чтобы заполнить наш ImageSource
либо Xamarin.Forms
ресурсом, либо FontImageSource
, добавьте также эти два метода:
public static void PlaceholderFromResource (string resourceName, Assembly assembly) => PlaceholderImageSource = ImageSource.FromResource (resourceName, assembly); public static void PlaceholderFromFontImageSource (FontImageSource fontImageSource) => PlaceholderImageSource = fontImageSource;
Теперь, когда у нас есть PlaceholderImageSource
, нам нужно расширить класс GlideExtensions
. Сначала мы реализуем обработчик для FontImageSource
. Обработчик Xamarin.Forms
для FontImageSource
предоставляет нам растровое изображение, которое мы собираемся использовать в качестве заполнителя. У меня это работает только с методом AsDrawable
, метод AsBitmap
всегда выдает исключение, потому что он не может преобразовать Bitmap
в Drawable
(я не исследовал это дальше).
private static async Task<RequestBuilder?> HandleFontImageSource (RequestManager request, Context? context, FontImageSource fontImageSource, CancellationToken token, Func<bool> cancelled) { if (context == null) return null; var defaultHandler = new Xamarin.Forms.Platform.Android.FontImageSourceHandler (); var bitmap = await defaultHandler.LoadImageAsync (fontImageSource, context, token); if (token.IsCancellationRequested || cancelled()) return null; if (bitmap == null) return null; return request.AsDrawable().Load (bitmap); }
Что касается метода HandleFontImageSource
, мне также нужно было изменить возвращаемое значение метода HandleStreamImageSource
, чтобы использовать метод AsDrawable
, иначе мы получим то же исключение, что и с FontImageSource
:
static async Task<RequestBuilder?> HandleStreamImageSource (RequestManager request, StreamImageSource source, CancellationToken token, Func<bool> cancelled) { //code omitted for readability return request.AsDrawable().Load (memoryStream.ToArray ()); }
Последние шаги, чтобы заставить все это работать, выполняются LoadViaGlide
методом. Сначала добавьте еще одну переменную RequestBuilder?
и назовите ее errorBuilder
:
RequestBuilder? errorBuilder = null;
После переключателя, который обрабатывает параметр source
, добавьте следующие строки кода:
switch(Forms.PlaceholderImageSource) { case StreamImageSource streamSource: errorBuilder = await HandleStreamImageSource (request, streamSource, token, () => !IsActivityAlive (imageView, Forms.PlaceholderImageSource)); break; case FontImageSource fontImageSource: errorBuilder = await HandleFontImageSource(request, imageView.Context, fontImageSource, token, () => !IsActivityAlive (imageView, Forms.PlaceholderImageSource)); break; default: errorBuilder = null; break; } if (errorBuilder != null) builder?.Error (errorBuilder);
Мы обращаемся с нашим PlaceholderImageSource
так же, как с ImageSource
, который мы собираемся загрузить. Если у нас есть действительный errorBuilder
, мы передаем его всему процессу. С этим у нас уже все на месте. Давайте посмотрим, как использовать это в вашем приложении.
Как использовать его в своем проекте Xamarin.Forms - Android
Перейдите к классу MainActivity
в своем проекте Android и добавьте следующий метод:
private void AttachGlide() { Android.Glide.Forms.Init(this, null, false); //recommended way of loading resource images=> //Android.Glide.Forms.Init(this, new GlideWithAndroidResourcePlaceholder(), false); //Xamarin Forms resource image //Android.Glide.Forms.PlaceholderFromResource("CachedImageTest.MSicc_Logo_Base_Blue_1024px_pad25.png", Assembly.GetAssembly(typeof(MainViewModel))); //FontImageSource Android.Glide.Forms.PlaceholderFromFontImageSource(new FontImageSource { Glyph = XfNativeCachedImages.Resources.MaterialDesignIcons.ImageBroken, FontFamily = "MaterialDesignIcons", Color = Xamarin.Forms.Color.Red }); }
Библиотеку Glide нужно инициализировать. В зависимости от того, какой метод вы используете, это можно сделать по-разному. Вышеупомянутый метод показывает их все, вам просто нужно изменить закомментированный код, чтобы поэкспериментировать с ним в образце (ссылка в конце сообщения). Механизм похож на тот, который я использовал для iOS и пакета Nuke.
Если вы последовали (или загрузили образец), вы должны увидеть результат, аналогичный следующему:
Вывод
Как и в случае с iOS, теперь мы также используем собственное кэширование и обработку изображений в Android. На то, чтобы запустить его, у меня ушло немало времени, но оно того стоило. Образец содержит более пятисот удаленных изображений, загруженных в CollectionView
. Проверьте, насколько плавная прокрутка (даже с DataBinding!).
Вы можете найти образец здесь на Github, а модифицированная версия glidex.forms доступна здесь. Как всегда, я надеюсь, что этот пост будет полезен для некоторых из вас.
До следующего поста, желаю всем счастливого кодирования!
Первоначально опубликовано на https://msicc.net 26 марта 2021 г.