Xamarin中的调用目标已引发异常

编程入门 行业动态 更新时间:2024-10-25 22:29:17
本文介绍了Xamarin中的调用目标已引发异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

这是代码(运行此代码以查看问题所在) => github/x0axz/CustomRenderer

在我的Xamarin应用程序中,有一个用于Android的自定义相机渲染器,它是通过 MessagingCenter从 ViewModel 调用的./code>.

In my Xamarin App, there is a Custom Camera Renderer for Android, which is being called from ViewModel through MessagingCenter.Send<object>(this, "A");.

一切正常.唯一的问题是,它在第​​一页上显示图片,但是当我导航到另一页时,还有另一个命令 MessagingCenter.Send< object>(this,"A"); ,以拍摄照片,但这一次它返回错误在调用Camera.release()之后正在使用相机.

It's working fine. The only problem is that, on first page it takes Picture, but when I navigate to another page, where there is an other command, MessagingCenter.Send<object>(this, "A");, to take a Picture, but this time it returns an error Camera is being used after Camera.release() was called.

下面是ViewModel和Camera Renderer的代码.

Below is the code for ViewModel and Camera Renderer.

FirstCameraViewModel.cs

private void FirstCamera(object sender, EventArgs e) { try { MessagingCenter.Send<object>(this, "A"); } catch { Console.WriteLine(error.InnerException.StackTrace); Console.WriteLine(error.InnerException.Message); } finally { timer_countdown = new Timer(); timer_countdown.Interval = 1000; timer_countdown.Elapsed += OnTimedEvent; timer_countdown.Enabled = true; timer_countdown.AutoReset = true; timer_countdown.Start(); } } private void OnTimedEvent(object source, ElapsedEventArgs e) { Seconds++; if (Seconds == 5) { MainThread.BeginInvokeOnMainThread(async () => { await NavigationService.NavigateToAsync<SecondCameraViewModel>(); }); } }

SecondCameraViewModel.cs,在此页面中返回错误

private void SecondCamera(object sender, EventArgs e) { try { MessagingCenter.Send<object>(this, "A"); } catch { Console.WriteLine(error.InnerException.StackTrace); Console.WriteLine(error.InnerException.Message); } finally { timer_countdown = new Timer(); timer_countdown.Interval = 1000; timer_countdown.Elapsed += OnTimedEvent; timer_countdown.Enabled = true; timer_countdown.AutoReset = true; timer_countdown.Start(); } } private void OnTimedEvent(object source, ElapsedEventArgs e) { Seconds++; if (Seconds == 5) { MainThread.BeginInvokeOnMainThread(async () => { await NavigationService.NavigateToAsync<IndexViewModel>(); }); } }

更新

CameraPreview.cs

public sealed class CameraPreview : ViewGroup, ISurfaceHolderCallback, Camera.IPictureCallback { SurfaceView surfaceView; ISurfaceHolder holder; Camera.Size previewSize; IList<Camera.Size> supportedPreviewSizes; Camera camera; IWindowManager windowManager; public bool IsPreviewing { get; set; } public Camera Preview { get { return camera; } set { camera = value; if (camera != null) { supportedPreviewSizes = Preview.GetParameters().SupportedPreviewSizes; RequestLayout(); } } } public CameraPreview(Context context) : base(context) { surfaceView = new SurfaceView(context); AddView(surfaceView); windowManager = Context.GetSystemService(Context.WindowService).JavaCast<IWindowManager>(); IsPreviewing = false; holder = surfaceView.Holder; holder.AddCallback(this); MessagingCenter.Subscribe<object>(this, "A", (e) => { camera.TakePicture(null, null, this); }); } protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = ResolveSize(SuggestedMinimumWidth, widthMeasureSpec); int height = ResolveSize(SuggestedMinimumHeight, heightMeasureSpec); SetMeasuredDimension(width, height); if (supportedPreviewSizes != null) { previewSize = GetOptimalPreviewSize(supportedPreviewSizes, width, height); } } protected override void OnLayout(bool changed, int l, int t, int r, int b) { var msw = MeasureSpec.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly); var msh = MeasureSpec.MakeMeasureSpec(b - t, MeasureSpecMode.Exactly); surfaceView.Measure(msw, msh); surfaceView.Layout(0, 0, r - l, b - t); } public void SurfaceCreated(ISurfaceHolder holder) { try { if (Preview != null) { Preview.SetPreviewDisplay(holder); } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(@" ERROR: ", ex.Message); } } public void SurfaceDestroyed(ISurfaceHolder holder) { if (Preview != null) { Preview.StopPreview(); } } public void SurfaceChanged(ISurfaceHolder holder, Android.Graphics.Format format, int width, int height) { var parameters = Preview.GetParameters(); parameters.SetPreviewSize(previewSize.Width, previewSize.Height); RequestLayout(); switch (windowManager.DefaultDisplay.Rotation) { case SurfaceOrientation.Rotation0: camera.SetDisplayOrientation(90); break; case SurfaceOrientation.Rotation90: camera.SetDisplayOrientation(0); break; case SurfaceOrientation.Rotation270: camera.SetDisplayOrientation(180); break; } Preview.SetParameters(parameters); Preview.StartPreview(); IsPreviewing = true; } Camera.Size GetOptimalPreviewSize(IList<Camera.Size> sizes, int w, int h) { const double AspectTolerance = 0.1; double targetRatio = (double)w / h; if (sizes == null) { return null; } Camera.Size optimalSize = null; double minDiff = double.MaxValue; int targetHeight = h; foreach (Camera.Size size in sizes) { double ratio = (double)size.Width / size.Height; if (Math.Abs(ratio - targetRatio) > AspectTolerance) continue; if (Math.Abs(size.Height - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.Abs(size.Height - targetHeight); } } if (optimalSize == null) { minDiff = double.MaxValue; foreach (Camera.Size size in sizes) { if (Math.Abs(size.Height - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.Abs(size.Height - targetHeight); } } } return optimalSize; } public void OnPictureTaken(byte[] data, Camera camera) { camera.StopPreview(); FileOutputStream outStream = null; File dataDir = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDcim); if (data != null) { try { TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); var s = ts.TotalMilliseconds; outStream = new FileOutputStream(dataDir + "/" + s + ".jpg"); outStream.Write(data); outStream.Close(); } catch (FileNotFoundException e) { System.Console.Out.WriteLine(e.Message); } catch (IOException ie) { System.Console.Out.WriteLine(ie.Message); } } camera.StartPreview(); } }

CameraPreviewRenderer.cs

public class CameraPreviewRenderer : ViewRenderer<Mobile.App.CameraPreview, CameraPreview> { CameraPreview cameraPreview; public CameraPreviewRenderer(Context context) : base(context) { } protected override void OnElementChanged(ElementChangedEventArgs<Mobile.App.CameraPreview> e) { base.OnElementChanged(e); if (e.OldElement != null) { // Unsubscribe cameraPreview.Click -= OnCameraPreviewClicked; } if (e.NewElement != null) { if (Control == null) { cameraPreview = new CameraPreview(Context); SetNativeControl(cameraPreview); } Control.Preview = Camera.Open((int)e.NewElement.Camera); // Subscribe cameraPreview.Click += OnCameraPreviewClicked; } } void OnCameraPreviewClicked(object sender, EventArgs e) { if (cameraPreview.IsPreviewing) { cameraPreview.Preview.StopPreview(); cameraPreview.IsPreviewing = false; } else { cameraPreview.Preview.StartPreview(); cameraPreview.IsPreviewing = true; } } protected override void Dispose(bool disposing) { if (disposing) { Control.Preview.Release(); } base.Dispose(disposing); } }

推荐答案

您将必须取消订阅MessagingCenter.

You will have to Unsubscribe the MessagingCenter.

共享项目中的CameraPreview.cs

CameraPreview.cs in shared project

public event EventHandler Subscribe; public event EventHandler Unsubscribe; public void OnSubscribe() { if (Subscribe != null) { Subscribe(this, EventArgs.Empty); } } public void OnUnsubscribe() { if (Unsubscribe != null) { Unsubscribe(this, EventArgs.Empty); } }

MainPage.xaml

MainPage.xaml

<local:CameraPreview Camera="Rear" x:Name="CameraPreview" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />

MainPage.xaml.cs

MainPage.xaml.cs

protected override void OnAppearing() { base.OnAppearing(); CameraPreview.OnSubscribe(); } protected override void OnDisappearing() { base.OnDisappearing(); CameraPreview.OnUnsubscribe(); }

FirstCameraPage.xaml

FirstCameraPage.xaml

<local:CameraPreview x:Name="CameraPreview" Camera="Rear" HorizontalOptions="CenterAndExpand" VerticalOptions="FillAndExpand" WidthRequest="250"/>

FirstCameraPage.xaml.cs

FirstCameraPage.xaml.cs

protected override void OnAppearing() { base.OnAppearing(); CameraPreview.OnSubscribe(); } protected override void OnDisappearing() { base.OnDisappearing(); CameraPreview.OnUnsubscribe(); }

android项目中的CameraViewRenderer.cs

CameraViewRenderer.cs in android project

protected override void OnElementChanged(ElementChangedEventArgs<CustomRenderer.CameraPreview> e) { base.OnElementChanged(e); if (e.OldElement != null) { // Unsubscribe cameraPreview.Click -= OnCameraPreviewClicked; } if (e.NewElement != null) { if (Control == null) { cameraPreview = new CameraPreview(Context); SetNativeControl(cameraPreview); } Control.Preview = Camera.Open(); e.NewElement.Subscribe += (sender, e) => { Control.Subscribe(); }; e.NewElement.Unsubscribe += (sender, e) => { Control.Unsubscribe(); }; // Subscribe cameraPreview.Click += OnCameraPreviewClicked; } }

Android项目中的CameraPreview.cs,添加以下方法.

CameraPreview.cs in android project, Add below methods.

internal void Subscribe() { MessagingCenter.Subscribe<object>(this, "A", (e) => { this.Preview.TakePicture(null, null, this); }); } internal void Unsubscribe() { MessagingCenter.Unsubscribe<object>(this, "A"); }

并从构造函数中删除MessagingCenter订阅

and remove MessagingCenter subscription from constructor

public CameraPreview (Context context) : base (context) { surfaceView = new SurfaceView (context); AddView (surfaceView); windowManager = Context.GetSystemService (Context.WindowService).JavaCast<IWindowManager> (); IsPreviewing = false; holder = surfaceView.Holder; holder.AddCallback (this); //MessagingCenter.Subscribe<object>(this, "A", (e) => //{ // this.Preview.TakePicture(null, null, this); //}); }

更多推荐

Xamarin中的调用目标已引发异常

本文发布于:2023-11-04 17:38:34,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1558581.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:异常   目标   Xamarin

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!