.NET MAUI — ObjectDispose_Generic ObjectDispose_ObjectName_Name, Microsoft.Maui.Platform.LayoutViewGroupAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 .NET MAUI — ObjectDispose_Generic ObjectDispose_ObjectName_Name, Microsoft.Maui.Platform.LayoutViewGroup

Сообщение Anonymous »

В настоящее время я разрабатываю приложение с использованием .NET MAUI (v8.0.90) и CommunityToolKit.Mvvm, и, что бы я ни пытался, я не могу решить следующую проблему.
Приложение (Android 14, API 34) работает около 9 часов в день и время от времени выдает следующее исключение:
ObjectDisposed_Generic ObjectDisposed_ObjectName_Name, Microsoft.Maui.Platform.LayoutViewGroup
at Java.Interop.JniPeerMembers.AssertSelf(IJavaPeerable )\n
at Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeNonvirtualObjectMethod(String , IJavaPeerable , JniArgumentValue* )\n
at Android.Views.View.get_Parent()\n
at Microsoft.Maui.ViewHandlerExtensions.PlatformArrangeHandler(IViewHandler viewHandler, Rect frame)\n
at Microsoft.Maui.Handlers.ViewHandler`2[[Microsoft.Maui.ILayout, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Platform.LayoutViewGroup, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].PlatformArrange(Rect frame)\n
at Microsoft.Maui.Controls.VisualElement.ArrangeOverride(Rect bounds)\n
at Microsoft.Maui.Controls.VisualElement.Microsoft.Maui.IView.Arrange(Rect bounds)\n
at Microsoft.Maui.Controls.Compatibility.Layout.LayoutChildIntoBoundingRegion(VisualElement child, Rect region)\n
at Microsoft.Maui.Controls.TemplatedView.LayoutChildren(Double x, Double y, Double width, Double height)\n
at Microsoft.Maui.Controls.Compatibility.Layout.UpdateChildrenLayout()\n
at Microsoft.Maui.Controls.Compatibility.Layout.OnIsVisibleChanged(Boolean oldValue, Boolean newValue)\n
at Microsoft.Maui.Controls.VisualElement.c.b__426_6(BindableObject bindable, Object oldvalue, Object newvalue)\n
at Microsoft.Maui.Controls.BindableObject.SetValueActual(BindableProperty property, BindablePropertyContext context, Object value, Boolean currentlyApplying, SetValueFlags attributes, SetterSpecificity specificity, Boolean silent)\n
at Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes, SetterSpecificity specificity)\n
at Microsoft.Maui.Controls.Internals.TypedBinding`2[[MDC_Room.Model.People.ChildListTabletDto, MDC_Room, Version=4.5.0.0, Culture=neutral, PublicKeyToken=null],[System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ApplyCore(Object sourceObject, BindableObject target, BindableProperty property, Boolean fromTarget, SetterSpecificity specificity)\n
at Microsoft.Maui.Controls.Internals.TypedBinding`2[[MDC_Room.Model.People.ChildListTabletDto, MDC_Room, Version=4.5.0.0, Culture=neutral, PublicKeyToken=null],[System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Apply(Boolean fromTarget)\n
at Microsoft.Maui.Controls.Internals.TypedBinding`2.PropertyChangedProxy[[MDC_Room.Model.People.ChildListTabletDto, MDC_Room, Version=4.5.0.0, Culture=neutral, PublicKeyToken=null],[System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].b__16_0()\n
at Microsoft.Maui.Controls.DispatcherExtensions.DispatchIfRequired(IDispatcher dispatcher, Action action)\n
at Microsoft.Maui.Controls.Internals.TypedBinding`2.PropertyChangedProxy[[MDC_Room.Model.People.ChildListTabletDto, MDC_Room, Version=4.5.0.0, Culture=neutral, PublicKeyToken=null],[System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].OnPropertyChanged(Object sender, PropertyChangedEventArgs e)\n
at Microsoft.Maui.Controls.BindingExpression.WeakPropertyChangedProxy.OnPropertyChanged(Object sender, PropertyChangedEventArgs e)\n
at CommunityToolkit.Mvvm.ComponentModel.ObservableObject.OnPropertyChanged(PropertyChangedEventArgs )\n
at MDC_Room.Model.People.ChildListTabletDto.set_Status(Status value)\n
at MDC_Room.Services.ChatHubEventHandlerService.OnChildStatusChanged(OnStatusChangeDto dto)

public async void OnChildStatusChanged(OnStatusChangeDto dto)
{
var appShellContext = AppUtility.GetAppShellViewModel();
try
{
if (dto.Room.Id != appShellContext.RoomId)
return;
var child = appShellContext.Children?.FirstOrDefault(x => x.Id == dto.Person.Id);
if (child != null)
{
if (child.Status != (Status)dto.Status)
{
child.Status = (Status)dto.Status;

if (child.Status == Status.Away)
child.IsNapping = false;
else
child.RId = appShellContext.RoomId;

await appShellContext._appShellEventHandler.ChildUpdated();
}
}
else
await appShellContext.LoadChildrenAsync();
}
catch (Exception ex)
{
await appShellContext.LoadChildrenAsync();
await _errorService.LogErrorAsync(ex, $"{nameof(ChatHubEventHandlerService)}.{nameof(OnChildStatusChanged)}");
}


Приложение было обновлено и теперь преобразует все элементы Frame в элементы Border. Frame вообще не используется!
Нарушающая функция находится на главной странице приложения, где оно обновляет свойство данной записи, ожидая, что его представление переключится между двумя изображениями ( В гостях/Присутствует). Возможно, также важно, что операция выполняется асинхронно через SignalR.
Домашняя страница теперь создается как одноэлементный (не уверен, что это правильный шаблон по сравнению с Transient, это то, что предлагают документы MS и другие пользователи SO). ):
builder.Services.AddSingleton();
builder.Services.AddSingleton();
builder.Services.AddSingleton();
builder.Services.AddSingleton();

XAML не представляет собой ничего особенного, на главной странице есть элемент управления с CollectionView, где каждая запись скрывает/показывает изображение в зависимости от статуса записи:









0




... removed for clarity



















Для ясности удален некоторый код из приведенного выше XAML.
Я думаю, что уперся в стену и не знаю, что еще попробовать, любая помощь буду очень признателен.
Я безуспешно прочитал все статьи по этой теме, которые смог найти, особенно:
  • Ошибка .NET MAUI: «Невозможно получить доступ к удаленному объекту. Имя объекта: 'Microsoft.Maui.Platform.ContentViewGroup'»
  • System.ObjectDisposeException: 'Невозможно получить доступ к удаленному объекту . Имя объекта: «Microsoft.Maui.Controls.Handlers.Compatibility.FrameRenderer».
Обновление: дополнительная информация о OnChildStatusChanged
OnChildStatusChanged вызывается через PopupPage CommunityToolkit после того, как ребенок входит в систему или выходит из нее. После вызова он извлекает статический список дочерних элементов, хранящийся в AppShellViewModel (при запуске), находит отдельную запись, загруженную через всплывающее окно, и обновляет ее статус. После закрытия всплывающего окна домашняя страница также обновляется, поскольку ее CollectionView привязан к тому же списку дочерних элементов.
При загрузке приложение загружает и сохраняет основной список дочерних элементов:< /p>
public partial class AppShellViewModel : BaseViewModel
{
... //code omitted for brevity

// changed to static b/c I thought maybe this was the root cause
[ObservableProperty]
static ObservableCollection? _children;
...

public partial class ChildListTabletDto : ObservableObject, ITabletPerson
{
... //code omitted for brevity

public bool IsPresent => Status == Status.Present;
public bool IsAway => Status == Status.Away;

[ObservableProperty]
[NotifyPropertyChangedFor(nameof(IsPresent))]
[NotifyPropertyChangedFor(nameof(IsAway))]
public Status _status;

Свойство IsAway/IsPresent, указанное выше, привязано к свойству IsVisible изображения в представлении.






После того, как приложение загрузится и перейдет на домашнюю страницу:
  • Пользователь выбирает дочерний элемент/запись (через TappedAsync) и загружен экземпляр CommunityToolkit PopupPage:
[RelayCommand]
public async Task TappedAsync(ChildListTabletDto child)
{
try
{
var vm = new ChildDetailPageViewModel(_tabletService, _attendanceService, _chatHubEventHandlerService, _noteService, _popupNavigation, _errorService, _dailyReportService, _sunscreenService, _repellantService, _cacheService)
{
ChildId = child.Id
};
var page = new ChildDetailPage(vm);
await _popupNavigation.PopAllAsync(false);
await _popupNavigation.PushAsync(page, false);
await vm.InitializeAsync();
}
catch (Exception ex)
{
await _errorService.LogErrorAsync(ex, $"{nameof(ChildListPageViewModel)}.{nameof(TappedAsync)}");
}
}
  • На всплывающей странице нажимается кнопка входа/выхода, дочерний статус обновляется в основном списке (поэтому изменения отражаются на домашнюю страницу после закрытия всплывающего окна без необходимости повторного вызова API):
[RelayCommand]
internal async Task SignInAsync()
{
await _popupNavigation.PopAsync();

AppShellViewModel appShellContext = AppUtility.GetAppShellViewModel();
IsBusy = true;

_chatHubEventHandlerService.OnChildStatusChanged(new OnStatusChangeDto
{
Room = new Model.Common.SelectDataDto
{
Id = appShellContext.RoomId,
Label = appShellContext.RoomName
},
Status = 1,
Person = new Model.Common.SelectDataDto
{
Id = ChildId,
Label = Child!.FormattedName
}
});
// API call
await _attendanceService.SignInChildAsync(ChildId, appShellContext.RoomId, null);
IsBusy = false;
}



Подробнее здесь: https://stackoverflow.com/questions/790 ... rosoft-mau
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»