summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.Android
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Platform.Android')
-rw-r--r--Xamarin.Forms.Platform.Android/Extensions/ImageViewExtensions.cs35
-rw-r--r--Xamarin.Forms.Platform.Android/Extensions/JavaObjectExtensions.cs12
-rw-r--r--Xamarin.Forms.Platform.Android/FastRenderers/ImageRenderer.cs86
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/FileImageSourceHandler.cs13
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ImageLoaderSourceHandler.cs14
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ImageRenderer.cs48
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/StreamImagesourceHandler.cs14
-rw-r--r--Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android.csproj1
8 files changed, 173 insertions, 50 deletions
diff --git a/Xamarin.Forms.Platform.Android/Extensions/ImageViewExtensions.cs b/Xamarin.Forms.Platform.Android/Extensions/ImageViewExtensions.cs
index f60acb7e..d0cd2045 100644
--- a/Xamarin.Forms.Platform.Android/Extensions/ImageViewExtensions.cs
+++ b/Xamarin.Forms.Platform.Android/Extensions/ImageViewExtensions.cs
@@ -1,28 +1,33 @@
using System;
using System.Threading.Tasks;
using Android.Graphics;
-using Java.IO;
using AImageView = Android.Widget.ImageView;
namespace Xamarin.Forms.Platform.Android
{
internal static class ImageViewExtensions
{
- public static async void UpdateBitmap(this AImageView imageView, Image newImage, Image previousImage = null)
+ // TODO hartez 2017/04/07 09:33:03 Review this again, not sure it's handling the transition from previousImage to 'null' newImage correctly
+ public static async Task UpdateBitmap(this AImageView imageView, Image newImage, Image previousImage = null)
{
+ if (imageView == null || imageView.IsDisposed())
+ return;
+
if (Device.IsInvokeRequired)
throw new InvalidOperationException("Image Bitmap must not be updated from background thread");
if (previousImage != null && Equals(previousImage.Source, newImage.Source))
return;
- ((IImageController)newImage).SetIsLoading(true);
+ var imageController = newImage as IImageController;
+
+ imageController?.SetIsLoading(true);
- (imageView as IImageRendererController).SkipInvalidate();
+ (imageView as IImageRendererController)?.SkipInvalidate();
imageView.SetImageResource(global::Android.Resource.Color.Transparent);
- ImageSource source = newImage.Source;
+ ImageSource source = newImage?.Source;
Bitmap bitmap = null;
IImageSourceHandler handler;
@@ -34,10 +39,7 @@ namespace Xamarin.Forms.Platform.Android
}
catch (TaskCanceledException)
{
- }
- catch (IOException ex)
- {
- Internals.Log.Warning("Xamarin.Forms.Platform.Android.ImageRenderer", "Error updating bitmap: {0}", ex);
+ imageController?.SetIsLoading(false);
}
}
@@ -47,14 +49,19 @@ namespace Xamarin.Forms.Platform.Android
return;
}
- if (bitmap == null && source is FileImageSource)
- imageView.SetImageResource(ResourceManager.GetDrawableByName(((FileImageSource)source).File));
- else
- imageView.SetImageBitmap(bitmap);
+ if (!imageView.IsDisposed())
+ {
+ if (bitmap == null && source is FileImageSource)
+ imageView.SetImageResource(ResourceManager.GetDrawableByName(((FileImageSource)source).File));
+ else
+ {
+ imageView.SetImageBitmap(bitmap);
+ }
+ }
bitmap?.Dispose();
- ((IImageController)newImage).SetIsLoading(false);
+ imageController?.SetIsLoading(false);
((IVisualElementController)newImage).NativeSizeChanged();
}
}
diff --git a/Xamarin.Forms.Platform.Android/Extensions/JavaObjectExtensions.cs b/Xamarin.Forms.Platform.Android/Extensions/JavaObjectExtensions.cs
new file mode 100644
index 00000000..007d8759
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Extensions/JavaObjectExtensions.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal static class JavaObjectExtensions
+ {
+ public static bool IsDisposed(this Java.Lang.Object obj)
+ {
+ return obj.Handle == IntPtr.Zero;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/FastRenderers/ImageRenderer.cs b/Xamarin.Forms.Platform.Android/FastRenderers/ImageRenderer.cs
index 845ec449..5ca1bd20 100644
--- a/Xamarin.Forms.Platform.Android/FastRenderers/ImageRenderer.cs
+++ b/Xamarin.Forms.Platform.Android/FastRenderers/ImageRenderer.cs
@@ -1,8 +1,10 @@
using System;
using System.ComponentModel;
+using System.Threading.Tasks;
using AImageView = Android.Widget.ImageView;
using AView = Android.Views.View;
using Android.Views;
+using Xamarin.Forms.Internals;
namespace Xamarin.Forms.Platform.Android.FastRenderers
{
@@ -17,30 +19,32 @@ namespace Xamarin.Forms.Platform.Android.FastRenderers
protected override void Dispose(bool disposing)
{
- base.Dispose(disposing);
-
if (_disposed)
return;
_disposed = true;
- if (!disposing)
- return;
-
- if (_visualElementTracker != null)
+ if (disposing)
{
- _visualElementTracker.Dispose();
- _visualElementTracker = null;
+ if (_visualElementTracker != null)
+ {
+ _visualElementTracker.Dispose();
+ _visualElementTracker = null;
+ }
+
+ if (_visualElementRenderer != null)
+ {
+ _visualElementRenderer.Dispose();
+ _visualElementRenderer = null;
+ }
+
+ if (_element != null)
+ {
+ _element.PropertyChanged -= OnElementPropertyChanged;
+ }
}
- if (_visualElementRenderer != null)
- {
- _visualElementRenderer.Dispose();
- _visualElementRenderer = null;
- }
-
- if (_element != null)
- _element.PropertyChanged -= OnElementPropertyChanged;
+ base.Dispose(disposing);
}
public override void Invalidate()
@@ -54,9 +58,9 @@ namespace Xamarin.Forms.Platform.Android.FastRenderers
base.Invalidate();
}
- protected virtual void OnElementChanged(ElementChangedEventArgs<Image> e)
+ protected virtual async void OnElementChanged(ElementChangedEventArgs<Image> e)
{
- this.UpdateBitmap(e.NewElement, e.OldElement);
+ await TryUpdateBitmap(e.OldElement);
UpdateAspect();
ElementChanged?.Invoke(this, new VisualElementChangedEventArgs(e.OldElement, e.NewElement));
@@ -77,6 +81,11 @@ namespace Xamarin.Forms.Platform.Android.FastRenderers
SizeRequest IVisualElementRenderer.GetDesiredSize(int widthConstraint, int heightConstraint)
{
+ if (_disposed)
+ {
+ return new SizeRequest();
+ }
+
Measure(widthConstraint, heightConstraint);
return new SizeRequest(new Size(MeasuredWidth, MeasuredHeight), MinimumSize());
}
@@ -114,7 +123,7 @@ namespace Xamarin.Forms.Platform.Android.FastRenderers
_element?.SendViewInitialized(Control);
}
-
+
void IVisualElementRenderer.SetLabelFor(int? id)
{
if (_defaultLabelFor == null)
@@ -144,18 +153,53 @@ namespace Xamarin.Forms.Platform.Android.FastRenderers
{
}
- protected virtual void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ protected virtual async void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == Image.SourceProperty.PropertyName)
- this.UpdateBitmap(_element);
+ await TryUpdateBitmap();
else if (e.PropertyName == Image.AspectProperty.PropertyName)
UpdateAspect();
ElementPropertyChanged?.Invoke(this, e);
}
+ protected virtual async Task TryUpdateBitmap(Image previous = null)
+ {
+ // By default we'll just catch and log any exceptions thrown by UpdateBitmap so they don't bring down
+ // the application; a custom renderer can override this method and handle exceptions from
+ // UpdateBitmap differently if it wants to
+
+ try
+ {
+ await UpdateBitmap(previous);
+ }
+ catch (Exception ex)
+ {
+ Log.Warning(nameof(ImageRenderer), "Error loading image: {0}", ex);
+ }
+ finally
+ {
+ ((IImageController)_element)?.SetIsLoading(false);
+ }
+ }
+
+ protected async Task UpdateBitmap(Image previous = null)
+ {
+ if (_element == null || _disposed)
+ {
+ return;
+ }
+
+ await Control.UpdateBitmap(_element, previous);
+ }
+
void UpdateAspect()
{
+ if (_element == null || _disposed)
+ {
+ return;
+ }
+
ScaleType type = _element.Aspect.ToScaleType();
SetScaleType(type);
}
diff --git a/Xamarin.Forms.Platform.Android/Renderers/FileImageSourceHandler.cs b/Xamarin.Forms.Platform.Android/Renderers/FileImageSourceHandler.cs
index 93124fef..95d66fb7 100644
--- a/Xamarin.Forms.Platform.Android/Renderers/FileImageSourceHandler.cs
+++ b/Xamarin.Forms.Platform.Android/Renderers/FileImageSourceHandler.cs
@@ -3,6 +3,7 @@ using System.Threading;
using System.Threading.Tasks;
using Android.Content;
using Android.Graphics;
+using Xamarin.Forms.Internals;
namespace Xamarin.Forms.Platform.Android
{
@@ -17,10 +18,18 @@ namespace Xamarin.Forms.Platform.Android
public async Task<Bitmap> LoadImageAsync(ImageSource imagesource, Context context, CancellationToken cancelationToken = default(CancellationToken))
{
string file = ((FileImageSource)imagesource).File;
+ Bitmap bitmap;
if (File.Exists (file))
- return !DecodeSynchronously ? (await BitmapFactory.DecodeFileAsync (file).ConfigureAwait (false)) : BitmapFactory.DecodeFile (file);
+ bitmap = !DecodeSynchronously ? (await BitmapFactory.DecodeFileAsync (file).ConfigureAwait (false)) : BitmapFactory.DecodeFile (file);
else
- return !DecodeSynchronously ? (await context.Resources.GetBitmapAsync (file).ConfigureAwait (false)) : context.Resources.GetBitmap (file);
+ bitmap = !DecodeSynchronously ? (await context.Resources.GetBitmapAsync (file).ConfigureAwait (false)) : context.Resources.GetBitmap (file);
+
+ if (bitmap == null)
+ {
+ Log.Warning(nameof(FileImageSourceHandler), "Could not find image or image file was invalid: {0}", imagesource);
+ }
+
+ return bitmap;
}
}
} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ImageLoaderSourceHandler.cs b/Xamarin.Forms.Platform.Android/Renderers/ImageLoaderSourceHandler.cs
index 8d0ae3d9..b22ca485 100644
--- a/Xamarin.Forms.Platform.Android/Renderers/ImageLoaderSourceHandler.cs
+++ b/Xamarin.Forms.Platform.Android/Renderers/ImageLoaderSourceHandler.cs
@@ -3,6 +3,7 @@ using System.Threading;
using System.Threading.Tasks;
using Android.Content;
using Android.Graphics;
+using Xamarin.Forms.Internals;
namespace Xamarin.Forms.Platform.Android
{
@@ -11,12 +12,19 @@ namespace Xamarin.Forms.Platform.Android
public async Task<Bitmap> LoadImageAsync(ImageSource imagesource, Context context, CancellationToken cancelationToken = default(CancellationToken))
{
var imageLoader = imagesource as UriImageSource;
- if (imageLoader != null && imageLoader.Uri != null)
+ Bitmap bitmap = null;
+ if (imageLoader?.Uri != null)
{
using (Stream imageStream = await imageLoader.GetStreamAsync(cancelationToken).ConfigureAwait(false))
- return await BitmapFactory.DecodeStreamAsync(imageStream).ConfigureAwait(false);
+ bitmap = await BitmapFactory.DecodeStreamAsync(imageStream).ConfigureAwait(false);
}
- return null;
+
+ if (bitmap == null)
+ {
+ Log.Warning(nameof(ImageLoaderSourceHandler), "Could not retrieve image or image data was invalid: {0}", imageLoader);
+ }
+
+ return bitmap;
}
}
} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ImageRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/ImageRenderer.cs
index 57937d89..43dac1fe 100644
--- a/Xamarin.Forms.Platform.Android/Renderers/ImageRenderer.cs
+++ b/Xamarin.Forms.Platform.Android/Renderers/ImageRenderer.cs
@@ -1,10 +1,10 @@
using System;
using System.ComponentModel;
+using System.Threading.Tasks;
using Android.Graphics;
using Android.Views;
using AImageView = Android.Widget.ImageView;
using Xamarin.Forms.Internals;
-using static Xamarin.Forms.Platform.Android.ImageViewExtensions;
namespace Xamarin.Forms.Platform.Android
{
@@ -20,7 +20,6 @@ namespace Xamarin.Forms.Platform.Android
public ImageRenderer()
{
- System.Diagnostics.Debug.WriteLine(">>>>> Old Image Renderer");
AutoPackage = false;
}
@@ -39,7 +38,7 @@ namespace Xamarin.Forms.Platform.Android
return new FormsImageView(Context);
}
- protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
+ protected override async void OnElementChanged(ElementChangedEventArgs<Image> e)
{
base.OnElementChanged(e);
@@ -50,28 +49,63 @@ namespace Xamarin.Forms.Platform.Android
}
_motionEventHelper.UpdateElement(e.NewElement);
-
- Control.UpdateBitmap(e.NewElement, e.OldElement);
+
+ await TryUpdateBitmap(e.OldElement);
UpdateAspect();
}
- protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ protected override async void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == Image.SourceProperty.PropertyName)
- Control.UpdateBitmap(Element);
+ await TryUpdateBitmap();
else if (e.PropertyName == Image.AspectProperty.PropertyName)
UpdateAspect();
}
void UpdateAspect()
{
+ if (Element == null || Control == null || Control.IsDisposed())
+ {
+ return;
+ }
+
AImageView.ScaleType type = Element.Aspect.ToScaleType();
Control.SetScaleType(type);
}
+ protected virtual async Task TryUpdateBitmap(Image previous = null)
+ {
+ // By default we'll just catch and log any exceptions thrown by UpdateBitmap so they don't bring down
+ // the application; a custom renderer can override this method and handle exceptions from
+ // UpdateBitmap differently if it wants to
+
+ try
+ {
+ await UpdateBitmap(previous);
+ }
+ catch (Exception ex)
+ {
+ Log.Warning(nameof(ImageRenderer), "Error loading image: {0}", ex);
+ }
+ finally
+ {
+ ((IImageController)Element)?.SetIsLoading(false);
+ }
+ }
+
+ protected async Task UpdateBitmap(Image previous = null)
+ {
+ if (Element == null || Control == null || Control.IsDisposed())
+ {
+ return;
+ }
+
+ await Control.UpdateBitmap(Element, previous);
+ }
+
public override bool OnTouchEvent(MotionEvent e)
{
if (base.OnTouchEvent(e))
diff --git a/Xamarin.Forms.Platform.Android/Renderers/StreamImagesourceHandler.cs b/Xamarin.Forms.Platform.Android/Renderers/StreamImagesourceHandler.cs
index 3128995d..a46e3abc 100644
--- a/Xamarin.Forms.Platform.Android/Renderers/StreamImagesourceHandler.cs
+++ b/Xamarin.Forms.Platform.Android/Renderers/StreamImagesourceHandler.cs
@@ -3,6 +3,7 @@ using System.Threading;
using System.Threading.Tasks;
using Android.Content;
using Android.Graphics;
+using Xamarin.Forms.Internals;
namespace Xamarin.Forms.Platform.Android
{
@@ -11,12 +12,19 @@ namespace Xamarin.Forms.Platform.Android
public async Task<Bitmap> LoadImageAsync(ImageSource imagesource, Context context, CancellationToken cancelationToken = default(CancellationToken))
{
var streamsource = imagesource as StreamImageSource;
- if (streamsource != null && streamsource.Stream != null)
+ Bitmap bitmap = null;
+ if (streamsource?.Stream != null)
{
using (Stream stream = await ((IStreamImageSource)streamsource).GetStreamAsync(cancelationToken).ConfigureAwait(false))
- return await BitmapFactory.DecodeStreamAsync(stream).ConfigureAwait(false);
+ bitmap = await BitmapFactory.DecodeStreamAsync(stream).ConfigureAwait(false);
}
- return null;
+
+ if (bitmap == null)
+ {
+ Log.Warning(nameof(ImageLoaderSourceHandler), "Image data was invalid: {0}", streamsource);
+ }
+
+ return bitmap;
}
}
} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android.csproj b/Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android.csproj
index bf5344ff..5100b873 100644
--- a/Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android.csproj
+++ b/Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android.csproj
@@ -103,6 +103,7 @@
<Compile Include="AndroidApplicationLifecycleState.cs" />
<Compile Include="AndroidTitleBarVisibility.cs" />
<Compile Include="AppCompat\FrameRenderer.cs" />
+ <Compile Include="Extensions\JavaObjectExtensions.cs" />
<Compile Include="FastRenderers\AccessibilityProvider.cs" />
<Compile Include="FastRenderers\ButtonRenderer.cs" />
<Compile Include="AppCompat\FormsViewPager.cs" />