Posted on 4. April 2024

Announcing .NET MAUI in .NET 8 Preview 6: Hello VS Code & VS for Mac

Анонс .NET MAUI у .NET 8 Preview 6: Hello VS Code & VS для Mac

.NET MAUI тепер доступний у .NET 8 Preview 6, в якому вирішено 23 важливих проблеми та впроваджено Native AOT для iOS. Крім того, сьогодні ви можете насолоджуватися .NET MAUI в .NET 8, використовуючи нове розширення .NET MAUI для коду Visual Studio, а також з випуском 17.6.1 Visual Studio для Mac.

Також доступний новий сервісний випуск .NET 7. Докладнішу інформацію можна знайти у примітках до випуску. Наразі команда зосереджена на якості .NET 8, а це означає, що для .NET 7 будуть випущені лише найважливіші виправлення. 

Виправлення та покращення в .NET MAUI

Вирішено декілька важливих проблем, пов'язаних зі шрифтами (#9104, #13239), навігацією (#7698, #15488, #9938), вкладками (#12386, #13239, #6929) та файловим провідником (#11088). Команда також продовжує роботу над покращенням керування пам'яттю та усуненням витоку адрес (#15062, #15303, #15831).

.NET 8 preview 6 представляє Native AOT (попередня компіляція) для iOS. Використовуючи цю функцію попереднього перегляду, ми спостерігаємо зменшення розміру додатків на 30-40% порівняно з Mono. Якщо вас зацікавила можливість досягти кращої продуктивності та зменшення розміру додатків для iOS, ознайомтеся з подробицями у статті про .NET 8 preview 6 у блозі.

Повний список виправлень можна знайти у примітках до випуску.

Представляємо VS Code (Preview)

На сьогодні вже випущено розширення .NET MAUI для Visual Studio Code, що забезпечує однаковий досвід розробки для Windows, macOS та Linux. Щоб дізнатися більше про розширення, прочитайте статтю Медді Монтакіли в блозі, де вона розповідає про нього.

screenshot of Visual Studio Code debugging a .NET MAUI app in an Android emulator

Як оновити

Visual Studio 2022 для Windows тепер містить попередні версії .NET 8 та робоче навантаження .NET MAUI. Завантажте останню попередню версію (17.7 Preview 3), виберіть робоче навантаження .NET Multi-platform App UI, а потім позначте додатковий компонент ".NET MAUI (.NET 8 Preview)".

Visual Studio installer checkbox for .NET MAUI and .NET 8 previews

Якщо ви використовуєте macOS, то тепер можете програмувати за допомогою Visual Studio для Mac, увімкнувши функцію попереднього перегляду для .NET 8 у Параметрах і встановивши .NET 8 preview 6 з інсталятора.

Enable .NET 8 in Visual Studio 2022 for Mac

Завантажте інсталятор .NET 8 preview 6, а потім встановіть .NET MAUI з командного рядка:

dotnet workload install maui


Поділіться своїми відгуками!

Ваші відгуки та внески в .NET MAUI дуже цінні. Ви можете повідомляти про проблеми, пропонувати функції або надсилати запити у репозиторії GitHub. Також ви можете приєднатися до сервера Discord або слідкувати за командою у Twitter, щоб бути в курсі останніх новин та оновлень.

 

Дякуємо за вашу підтримку і щасливого кодування!

Source



Posted on 14. March 2024

.NET MAUI Community Toolkit 2023 Highlights

Основні моменти .NET MAUI Community Toolkit 2023

 

Коли 2023 рік вже позаду, поміркуймо про шлях проєкту .NET MAUI Community Toolkit і про те, що чекає на нас далі. Ця бібліотека з відкритим вихідним кодом слугує доповненням до .NET MAUI, пропонуючи розробникам багатий набір елементів керування, конвертерів та помічників, призначених для прискорення розробки додатків на платформі .NET MAUI. Орієнтуючись на інновації, керовані спільнотою, вона стала незамінним інструментом для розробників, які прагнуть вдосконалити свої додатки .NET MAUI.

Це був рік, коли

Наш репозиторій на GitHub перетворився на динамічний центр активності, залучивши понад 40 учасників, які колективно просувають проєкт вперед. Ваші відгуки, пропозиції та внески коду допомогли зробити цей інструментарій більш потужним та ефективним ресурсом для розробників .NET MAUI.

У цифрах

 

  • 9 випусків: Відзначаючи постійний прогрес, ми випустили 9 значних випусків, кожен з яких додав більше цінності та можливостей до інструментарію.

  • 260 комітів: З кожним комітом ми покращували та розширювали функціональність інструментарію.

  • Змінено 521 файл: Відображаючи наш прогрес, ми оновили, покращили та оптимізували 521 файл, щоб забезпечити найвищі стандарти якості.

  • 41 дописувач: Велике вітання нашим активним членам спільноти! Ваші різноманітні погляди та досвід були життєво важливими для нашого спільного успіху.

  • Найкращі 5 комітерів: Особлива подяка brminnick, VladislavAntonyuk, jfversluis, pictos та cat0363. Ваша відданість та внесок були зразковими.

  • 4190 репозиторій залежать від нас: Понад 4190 репозиторіїв покладаються на CommunityToolkit.Maui, що є свідченням нашого впливу, який дедалі зростає.

  • 679 767 завантажень з NuGet: Неймовірна кількість завантажень цього року свідчить про широке розповсюдження та довіру до нашого інструментарію.

Важливі доповнення

Окрім величезної кількості виправлень, також додано суттєві можливості протягом 2023 року, ось короткий огляд ключових нових функцій, які ми інтегрували:

image showing the feature list and components of .NET MAUI Community Toolkit v7.0.1

  • Media Element: Пориньте у світ мультимедіа з нашим новим елементом керування Media Element. Незалежно від того, чи ви транслюєте потокове відео з Інтернету, чи використовуєте вбудовані ресурси, чи отримуєте доступ до локальних файлів, цей елемент керування безперешкодно відтворює відео- та аудіоконтент у ваших додатках .NET MAUI.

.NET MAUI Toolkit media element on phone

  • Інтеграція з картами Windows: Наша інтеграція з картами дозволяє використовувати можливості карт .NET MAUI безпосередньо на платформі Windows, покращуючи сервіси на основі визначення місцеперебування у ваших додатках.

  • SpeechToText і розпізнавання мовлення: Розкрийте потенціал голосу за допомогою наших функцій SpeechToText і розпізнавання мовлення. Взаємодійте та керуйте своїми програмами за допомогою усної мови, відкриваючи новий вимір доступності та зручності. Дізнайтеся більше про це в цій статті в блозі.

Відео

 

  • FolderPicker та FileSaver: Виведіть керування файлами на новий рівень. FolderPicker дозволяє користувачам легко переміщатися і вибирати каталоги, а FileSaver надає свободу вибору теки призначення і дозволяє легко зберігати файли.

Відео

 

  • Розширення клавіатури: Отримайте контроль над екранною клавіатурою. Перевіряйте її видимість, приховуйте її або викликайте за бажанням, забезпечуючи більш плавну та інтуїтивно зрозумілу роботу з клавіатурою у ваших додатках .NET MAUI.

  • Badge API: Представляємо Badge API - найпростіше рішення для відображення кількості сповіщень на іконках ваших додатків. Тримайте користувачів в курсі подій та інформуйте їх лише одним переглядом.

  • API для тематизації додатків: Ми розширили можливості стандартного інтерфейсу .NET MAUI, щоб полегшити вам налаштування та тематизацію ваших додатків, створюючи цікавіший та більш адаптований до бренду користувацький інтерфейс.

  • Підтримка .NET 8: Зважаючи на майбутнє, наша команда з гордістю підтримує .NET 8, гарантуючи, що ваші додатки отримають користь від останніх удосконалень, покращень безпеки та продуктивності, які пропонує фреймворк.

Але це ще не все

Інструментарій .NET MAUI Community Toolkit виходить за рамки основного пакета NuGet, ми також пишаємося нашою документацією, розміщеною в нашому репозиторії Docs, і універсальним пакетом .NET MAUI Markup для розробників, які схильні до підходу, що не використовує XAML. Обидва ці  компоненти інструментарію отримують постійні оновлення, про що свідчать:

Репозитарій документів:

  • Комітів: 192

  • Дописувачі: 25

  • Топ-5 дописувачів: bijington, jfversluis, brminnick, Sergio0694, VladislavAntonyuk

Репозиторій розмітки MAUI:

  • Зафіксовано: 104

  • Дописувачі: 9

  • Топ-5 дописувачів: brminnick, Youssef1313, bijington, VladislavAntonyuk, JoonghyunCho

Окрім цього, інструментарій .NET MAUI Community Toolkit з гордістю святкує визначну подію - понад 1 мільйон завантажень, що свідчить про його надійність, міцність та довіру, яку він завоював у спільноті розробників.

nuget download trend

Цей успіх підкреслює роль інструментарію як важливого активу в екосистемі .NET MAUI, що постійно розвивається, щоб дати розробникам можливість створювати неймовірні кросплатформні додатки.




Posted on 20. November 2023

Announcing .NET MAUI in .NET 8

Анонс .NET MAUI у .NET 8

Сьогодні наша команда рада представити вам останній великий стабільний реліз .NET MAUI у .NET 8! Ми створюємо .NET MAUI, щоб дозволити розробникам .NET створювати крос-платформні додатки для Android, iOS, macOS і Windows із глибокою вбудованою інтеграцією, власними користувальницькими інтерфейсами та гібридними можливостями, які розширюють можливості Blazor та інших технологій вебінтерфейс користувача. Сьогодні відзначається третій великий реліз.NET MAUI за останні 18 місяців, який зміщує кут уваги від нашого об’єднання платформи Xamarin із .NET до просування .NET як єдиного цілого.


На додаток до всієї чудової роботи над .NET SDK і середовищем виконання, ми зосередилися на .NET 8, щоб виправити серйозні помилки, ізолювати та усунути витоки пам’яті, підвищити точність і надійність гарячого перезавантаження, полегшити шлях для клієнтів, які оновлюють Xamarin, зберігають і покращують продуктивність під час запуску та виконання, і багато іншого. Ми дуже пишаємося цим релізом і не можемо дочекатися, поки всі почнуть його використовувати.


«Створення макетів справа наліво в .NET MAUI стало реальністю завдяки .NET 8. Візуальні елементи ідеально впорядковані, а каруселі тепер чудово працюють. Ми деякий час працювали з останніми версіями попереднього перегляду, і вдосконалення, зроблені командою MAUI, виявилися ключовими для успішної доставлення програм RTL нашим клієнтам». – Лео, UXDivers для Umrahme

справа наліво порівнює .net 8 і 7

Подібні перші відгуки були обнадійливими, і ми з нетерпінням чекаємо вашої думки. Давайте розглянемо деякі з найбільших покращень, які ви отримаєте в .NET MAUI.

Загальна якість

По-перше, дивлячись на реліз у цифрах, у .NET 8 ми маємо:

– Об’єднано 1618 pull requests (з 577)

– Вирішено 689 помилок (зі 180)


Порівняно з релізом .NET 7 GA це на 180% більше пулл реквестів та на 283% більше вирішених проблем із помилками. Оскільки .NET 7 був коротшим релізом для .NET MAUI, я подумав, що було б цікаво також включити всі випуски служби .NET 7. Беручи це до уваги, .NET 8 усе ще має на 18% більше пулл реквестів та на 13% більше вирішених проблем із помилками.

Це було б неможливо без 94 чудових співавторів у командах Microsoft і особливо в спільноті. Від імені всіх користувачів .NET MAUI ми щиро дякуємо за ваш внесок і підтримку!

Учасники розробки .NET MAUI у .NET 8

На початку обслуговування .NET 7 ми чітко й голосно почули від розробників, що нам потрібно підвищити якість релізів, і тому ми зробили саме це, піднявши планку того, що ми будемо резервно портувати з нашої роботи .NET 8 для релізів .NET 7 до у нас було більше автоматизованого тестування та інших процесів, щоб краще захиститися від цього. Під час наступних випусків ми ввімкнули неактивний набір тестів Xamarin.Forms для запуску в .NET і з .NET MAUI, а також додали понад 3500 тестів пристроїв у Windows, розповсюджених у областях Controls, Core і Essentials серед інших тестів.


У майбутньому в обслуговуванні .NET 8 планка повернулася, і ми надсилатимемо більше виправлень у .NET 8, ніж ви бачили в .NET 7. Ми знаємо, що це не було популярним рішенням, і ми зробили все можливе, щоб бути більш впевненими в якості наших релізів швидкого обслуговування для задоволення ваших потреб.

Основні сфери покращення якості:

– Поведінка клавіатури, особливо на мобільних пристроях

– Підтримка FlowDirection для мов із письмом справа наліво

– Точність компонування та продуктивність

– Продуктивність прокручування

– Управління пам'яттю


Перегляньте примітки до випуску , щоб отримати повний список виправлень і покращень.

Що нового

Родовід .NET MAUI бере свій початок у сенсорних інтерфейсах на мобільних і планшетних пристроях, тож нам потрібно ще трохи попрацювати, щоб створити більш зручну  взаємодію для настільного комп’ютера, де користувачі частіше вводять дані з клавіатури та миші. Цей випуск включає прискорювачі клавіатури, покращує жести вказівника тощо.

Клавіатурні прискорювачі

 

Прискорювач клавіатури – це комбінація клавіш, яку можна пов’язати з будь-яким пунктом меню в настільній програмі, наприклад копіювати (Ctrl+C), вставити (Ctrl+V) і вирізати (Ctrl+X).

Щоб отримати додаткові відомості та розширені приклади, перегляньте документацію про прискорювачі клавіатури .

Покращення жестів вказівника

.NET MAUI деякий час містив PointerGesture, щоб ви знали, коли курсор знаходиться над елементом, і тепер у .NET 8 ви отримуєте події PointerPressed та PointerReleased з аргументами подій, що містять більше інформації про положення вказівника. Це працює на Android, iPadOS, Mac Catalyst і Windows.


Перегляньте приклад у відеоплеєрі


Перегляньте оновлену документацію щодо розпізнавання жесту вказівника .

Покращення жестів перетягування

Щоб покращити роботу користувача з перетягуванням, ми розкрили більше API у Windows, зокрема включення спеціальних гліфів під час перетягування, користувацьких підписів під час перетягування, а також у iOS і Mac Catalyst для розміру елемента, який ви перетягуєте, додавання користувальницьких фігур чи зображень, а також налаштування дії скидання, щоб вказати, чи це копіювання, переміщення чи певна заборонена дія.

Перегляньте приклад у відеоплеєрі

Перегляньте інший приклад у відеоплеєрі

Перегляньте оновлену документацію щодо жестів перетягування та опускання.

Покращення продуктивності та пам'яті

Джонатан Пепперс детально написав про роботу в .NET 8, спрямовану на покращення продуктивності, розміру програми та усунення витоків пам’яті. Нові функції включають AndroidStripILAfterAOT, AndroidEnableMarshalMethods і NativeAOT для iOS. Ці та багато інших покращень доступні, тож ви можете вибрати найкращий шлях для зменшення розміру програми та підвищення продуктивності.

Залишаючись на передньому краї .NET, ви отримуєте більшість цих покращень без необхідності вносити будь-які зміни у свій код.

Різні моменти

З огляду на величезний обсяг зусиль, які були витрачені на створення цього релізу, не дивно, що є ще набагато більше того, що потрібно висвітлити. Щоб отримати повний перелік змін, прочитайте докладні примітки до випуску .NET MAUI 8.0.3 , а для скороченого підсумку насолодіться читанням: Що нового в .NET MAUI для .NET 8.

Опублікуйте незапаковану програму .NET MAUI для Windows за допомогою CLI .

– Використовуйте ContentPage.HideSoftInpuOnTapped, щоб закрити клавіатуру під час торкання будь-де на сторінці

– Елементи керування, які підтримують введення тексту, отримують методи розширення, які підтримують приховання та показ клавіатури програмного введення. Щоб отримати додаткові відомості, див. Приховати та показати програмну клавіатуру введення .

– WebView отримує властивість UserAgent. Для отримання додаткової інформації див. WebView .

– Вбудоване медіа-відтворення відео HTML5, включаючи автоматичне відтворення та картинку в картинці, увімкнено за замовчуванням для WebView на iOS. Додаткову інформацію див. у розділі Налаштування параметрів відтворення медіа на iOS і Mac Catalyst .

– BlazorWebView отримує властивість StartPath, метод TryDispatchAsync і розширені можливості логування. Щоб отримати додаткові відомості, перегляньте розділ Розміщення веб-програми Blazor у програмі .NET MAUI за допомогою BlazorWebView .

– Клас TapGestureRecognizer отримує можливість обробляти вторинні натискання на Android. Додаткову інформацію див. у розділі Розпізнавання жесту дотику .

Почніть сьогодні

.NET MAUI та .NET 8 включено в сьогоднішній стабільний реліз Visual Studio 2022 17.8 .

На всіх платформах ви можете розробляти з .NET MAUI за допомогою Visual Studio Code. Установіть розширення .NET MAUI і повідомте нам, як ми можемо покращити цей попередній перегляд для вас у майбутньому.


Завантажте програму встановлення .NET 8 , а потім інсталюйте .NET MAUI з командного рядка:

Через припинення використання Visual Studio для Mac наступного року ви зможете продовжувати розробку за допомогою Visual Studio для Mac після ввімкнення функції попереднього перегляду для .NET 8 у параметрах.

Щоб оновити проєкти до .NET 8, дотримуйтесь інструкцій з оновлення на нашій вікі.

Дякую

 

Від імені команди .NET MAUI дякую за вашу участь, внески та підтримку! Ми з нетерпінням чекаємо на ваші успіхи та ваші відгуки про те, як ми можемо покращити продукт за допомогою випусків служби .NET 8 і в .NET 9.




Posted on 10. November 2023

.NET 8 Performance Improvements in .NET MAUI

.NET 8 Вдосконалення продуктивності .NET 8 в .NET MAUI

 

Основна увага в .NET MAUI у релізі .NET 8 приділяється якості. Тому ми зосередилися на виправленні помилок замість того, щоб гнатися за високими показниками продуктивності. У .NET 8 ми об'єднали 1 559 запитів, які закрили 596 проблем. Вони включають зміни від команди .NET MAUI, а також від спільноти .NET MAUI. Ми оптимістично налаштовані, що це повинно призвести до значного підвищення якості в .NET 8.

Проте! У нас є ще багато змін у продуктивності, які ми можемо продемонструвати. Спираючись на фундаментальні покращення продуктивності  в .NET 8 ми постійно знаходимо легку здобич, і на GitHub були проблеми з продуктивністю, які ми намагалися вирішити. Наша мета — продовжувати робити .NET MAUI швидшим з кожним релізом, читайте далі, щоб дізнатися подробиці!


Огляд покращень продуктивності в попередніх релізах можна знайти в наших статтях для .NET 6 і 7. Це також дасть вам уявлення про покращення, які ви побачите при переході з Xamarin.Forms на .NET MAUI:

        .NET 7 Покращення продуктивності в .NET MAUI

        .NET 6 Покращення продуктивності в .NET MAUI


Зміст


Нові функції

-      AndroidStripILAfterAOT

-      AndroidEnableMarshalMethods

-      NativeAOT на iOS


Побудова та продуктивність внутрішнього циклу

-         Відфільтруйте вихідні дані Android ps -A за допомогою grep

-         Перенесення використання vcmeta.dll з WindowsAppSDK на C#

-        Покращення віддалених збірок iOS на Windows

-        Покращення внутрішнього циклу Android

-        Компіляція XAML більше не використовує LoadInSeparateAppDomain


Покращення продуктивності або розміру програми

-        Структури та IEquatable в .NET MAUI

-        Виправлено проблему продуктивності в {AppThemeBinding}

-        Зверніться до CA1307 та CA1309 для отримання інформації про продуктивність

-        Зверніться до CA1311 для отримання інформації

-        Видалення невикористаної події ViewAttachedToWindow на Android

-        Видаліть непотрібні System.Reflection для {Binding}

-        Використовуйте StringComparer.Ordinal для словника та хеш-набору

-        Зменшення взаємодії з Java у MauiDrawable на Android

-        Покращення продуктивності верстки Label на Android

-        Зменшення викликів взаємодії Java для елементів керування в .NET MAUI

-        Покращення продуктивності Entry.MaxLength на Android

-        Зменшення використання пам'яті CollectionView на Windows

-        Використовуйте атрибут UnmanagedCallersOnlyAttribute на платформах Apple

-        Швидша взаємодія з Java для рядків на Android

-        Швидша взаємодія з Java для подій C# на Android

-        Використання функціональних покажчиків для JNI

-        Видалено Xamarin.AndroidX.Legacy.Support.V4

-        Дедуплікація генериків на iOS та macOS

-        Виправлено реалізацію System.Linq.Expressions на iOS-подібних платформах

-        Встановіть DynamicCodeSupport=false для iOS та Catalyst


Витоки пам'яті

-        Витоки пам'яті та якість

-        Діагностика витоків в .NET MAUI

-        Патерни, що призводять до витоків: Події C#

-        Кільцеві посилання на платформах Apple

-        Аналізатор Roslyn для платформ Apple

Інструменти та документація

-        Спрощені dotnet-trace та dotnet-dsrouter

-        Підтримка мобільних пристроїв dotnet-gcdump 


Нові функції

AndroidStripILAfterAOT

Одного разу у нас виникла геніальна думка: якщо AOT попередньо компілює методи C#, то чи потрібен нам керований метод? Видалення тіла методу C# дозволило б зменшити розмір збірок.  Додатки .NET iOS вже роблять це, так чому б не зробити це і для Android?

Хоча ідея проста, реалізація не була такою: iOS використовує "повний" AOT, який перетворює всі методи AOT у форму, що не вимагає використання JIT під час виконання. Це дозволило iOS запустити cil-strip видаляючи всі тіла методів з усіх керованих типів.

На той час Xamarin.Android підтримував лише "звичайний" AOT, а звичайний AOT вимагає JIT для певних конструкцій, таких як узагальнені типи та узагальнені методи. Це означало, що спроба запустити cil-strip призведе до помилок під час виконання, якщо буде видалено тіло методу, яке насправді потрібно під час виконання. Це було особливо погано, оскільки cil-strip могла видалити лише всі тіла методів!

Ми повторно впроваджуємо IL-розбірку для .NET 8. Додаємо нову властивість $(AndroidStripILAfterAOT) для MSBuild. При значенні true завдання <MonoAOTCompiler/> буде відстежувати, які тіла методів були фактично AOT'ені, зберігаючи цю інформацію у %(_MonoAOTCompiledAssemblies.MethodTokenFile), а нове завдання <ILStrip/> буде оновлювати вхідні збірки, видаляючи всі тіла методів, які можна видалити.

 

За замовчуванням увімкнення $(AndroidStripILAfterAOT) замінить стандартне налаштування $(AndroidEnableProfiledAot), дозволяючи вилучити всі обрізані AOT'івські методи. Цей вибір було зроблено тому, що $(AndroidStripILAfterAOT) є найбільш корисним при AOT-компіляції всього вашого додатку. Профільоване вилучення AOT та IL можна використовувати разом, явно встановивши обидва параметри у файлі .csproj, але єдиною перевагою буде невелике зменшення розміру .apk:

.apk для нового додатку dotnet для Android:

Зауважте, що AndroidStripILAfterAOT=false та AndroidEnableProfiledAot=true є типовим середовищем конфігурації релізу, для 7.7MB.

Проєкт, який встановлює лише AndroidStripILAfterAOT=true, неявно встановлює AndroidEnableProfiledAot=false, призводить до отримання програми розміром 8.1 МБ.

Дивіться xamarin-android#8172 та dotnetdotnet/runtime#86722, щоб дізнатися більше про цю можливість.

AndroidEnableMarshalMethods

 

.NET 8 вводить нове експериментальне налаштування для конфігурацій Release:

Ми сподіваємося зробити цю функцію доступною за замовчуванням у .NET 9, але наразі ми надаємо цю можливість як експериментальну. Програми, які орієнтовані лише на одну архітектуру, наприклад RuntimeIdentifier=android-arm64, ймовірно, зможуть увімкнути цю функцію без проблем.

Загальні відомості про методи Маршала

Метод Маршала JNI - це вказівник на функцію, що викликається з JNI, який надається в JNIEnv::RegisterNatives(). Наразі маршальські методи JNI надаються через взаємодію між кодом, який ми генеруємо, та JNINativeWrapper.CreateDelegate():

-        Наш генератор коду видає "справжній" JNI метод, який можна викликати.

-         JNINativeWrapper.CreateDelegate() використовує System.Reflection.Emit для обгортки методу для обробки виключень.

Маршальські методи JNI потрібні для всіх переходів з Java на C#.

 

Розглянемо віртуальний метод Activity.OnCreate():

Activity.n_OnCreate_Landroid_os_Bundle_() - це метод маршала JNI, який відповідає за перетворення параметрів зі значень JNI у типи C#, перенаправлення виклику методу до Activity.OnCreate() та (за необхідності) перетворення значення, що повертається, назад до JNI.

Activity.GetOnCreate_Landroid_os_Bundle_Handler() є частиною інфраструктури реєстрації типів, надаючи екземпляр Delegate до RegisterNativeMembers .RegisterNativeMembers(), який згодом передається до JNIEnv::RegisterNatives().

Хоча це і працює, результат не є неймовірно продуктивним: якщо не використовувати один з оптимізованих типів делегатів, доданих в xamarin-android#6657, System.Reflection.Emit використовується для створення обгортки навколо методу marshal, чого ми намагалися уникати роками.

Отже, ідея: оскільки ми вже збираємо нативний інструментарій і використовуємо LLVM-IR для створення libxamarin-app.so, що, якби ми видали нативні імена методів Java і пропустили все, що було зроблено в рамках Runtime.register() і JNIEnv.RegisterJniNatives()?

 

Дано:

Під час збирання, libxamarin-app.so міститиме цю функцію:

Під час виконання програми, виклик Runtime.register(), присутній в Java викликається Java-обгортці, буде або пропущено, або не буде виконуватися, і Android/JNI натомість перетворить MyActivity.n_onCreate() у Java_crc..._MyActivity_n_1onCreate().

Ми називаємо цю роботу "LLVM Marshal Methods", яка наразі є експериментальною в .NET 8. Багато особливостей все ще досліджуються, і ця функція буде поширюватися на різні області.

Дивіться xamarin-android#7351, щоб дізнатися більше про цю експериментальну функцію.

NativeAOT на iOS

У .NET 7 ми почали експеримент, щоб побачити, що потрібно для підтримки NativeAOT на iOS. Перехід від прототипу до початкової реалізації: .NET 8 Preview 6 включав NativeAOT як експериментальну функцію для iOS.

 

Щоб вибрати NativeAOT у проєкті MAUI iOS, скористайтеся наступними налаштуваннями у файлі проєкту:

 

Потім створити додаток для iOS-пристрою:

Зауваження. Ми можемо розглянути можливість уніфікації та покращення назв властивостей MSBuild для цієї функції у майбутніх релізах .NET. Щоб виконати одноразову збірку у командному рядку, вам також може знадобитися вказати -p:PublishAotUsingRuntimePack=true на додаток до -p:PublishAot=true.

Однією з головних проблем першого релізу було те, як робоче навантаження iOS підтримує інтероперабельність Objective-C. Проблема була пов'язана в основному з системою реєстрації типів, яка є ключовим компонентом для ефективної підтримки iOS-подібних платформ (дивіться  документацію  для  деталей). У своїй реалізації система реєстрації типів залежить від токенів метаданих типів, які недоступні у NativeAOT. Тому, щоб скористатися перевагами високоефективного середовища виконання NativeAOT, нам довелося адаптуватися. dotnetdotnet/runtime#80912 містить обговорення того, як розв'язати цю проблему, і, нарешті, в xamarin-macios#18268 ми реалізували новий керований статичний реєстратор, який працює з NativeAOT. Новий керований статичний реєстратор не тільки сумісний з NativeAOT, але і набагато швидший за стандартний, і доступний для всіх підтримуваних середовищ виконання (див. у  документації for докладніше).

На цьому шляху нам дуже допомогла наша GH-спільнота, і їхній внесок (огляди коду, PR) був дуже важливим, щоб допомогти нам швидко рухатися вперед і випустити цю функцію вчасно. Ось деякі з багатьох PR, які допомогли нам і розблокували наш шлях:

-        dotnet/runtime#77956

-       dotnet/runtime#78280

-        dotnet/runtime#82317

-        dotnet/runtime#85996

і цей список можна продовжувати...

З появою .NET 8 Preview 6 ми нарешті змогли випустити нашу першу версію NativeAOT на iOS, яка також підтримує MAUI. Дивіться в  пост в блозі про .NET 8 Preview 6, щоб дізнатися більше про те, чого нам вдалося досягти в початковій версії.

У наступних випусках .NET 8 результати значно покращилися, оскільки ми виявляли та вирішували проблеми на цьому шляху. На графіку нижче показано порівняння розміру шаблонних додатків .NET MAUI для iOS у попередніх версіях:

Ми досягли стабільного прогресу і повідомили про очікувану економію розміру, завдяки вирішенню наступних проблем:

-        dotnet/runtime#87924 - виправлено серйозну проблему з розміром NativeAOT з AOT-несумісними шляхами коду у System.Linq.Expressions, а також зроблено повністю сумісними з NativeAOT при націлюванні на iOS

-        xamarin-macios#18332 - зменшено розмір розділу __LINKEDIT Export Info у вилучених двійкових файлах

Крім того, в останньому випуску RC 1 розмір додатків ще більше зменшився, досягнувши  на 50% меншого розміру для шаблонних додатків .NET MAUI для iOS порівняно з Mono. Найвпливовіші проблеми/ПР, які сприяли цьому:

-        xamarin-macios#18734 - Зробити Full  режимом з'єднання за замовчуванням для NativeAOT

-        xamarin-macios#18584 - Зробити обрізку кодової бази сумісним за допомогою серії PR.

Попри те, що розмір програми був основною метрикою, на якій ми зосередилися, для випуску RC 1 ми також виміряли час запуску для шаблонного додатка .NET MAUI для iOS, порівнюючи NativeAOT і Mono, де NativeAOT показав майже вдвічі швидший час запуску.

Основні висновки

Для сценаріїв NativeAOT на iOS зміна режиму зв'язування за замовчуванням на Full (xamarin-macios#18734), ймовірно, є найбільшим покращенням для розміру програми. Але водночас, ця зміна може призвести до поломки додатків, які не є повністю сумісними з AOT та обрізкою. У режимі Full, тример може обрізати несумісні з AOT шляхи коду (згадайте про використання рефлексії), доступ до яких здійснюється динамічно під час виконання. Режим зв'язування Full  не є типовою конфігурацією у разі використання середовища виконання Mono, тому деякі програми можуть бути не повністю сумісними з AOT.

Підтримка NativeAOT на iOS є експериментальною функцією і все ще перебуває в процесі розробки, і ми плануємо вирішувати потенційні проблеми з режимом повного посилання поступово:

-        Як перший крок, ми увімкнули попередження про обрізання, AOT та однофайлові попередження за замовчуванням у xamarin-macios#18571. Увімкнені попередження мають попередити наших клієнтів про те, що використання певного фреймворку, бібліотеки або деяких конструкцій C# у їхньому коді несумісне з NativeAOT - і може призвести до аварійного завершення роботи під час виконання. Ця інформація має допомогти нашим клієнтам писати  код сумісний з AOT, а також допомогти нам покращити наші фреймворки та бібліотеки з тією ж метою — повністю використати переваги компіляції AOT.

-        Другим кроком було усунення всіх попереджень від збірок Microsoft.iOS та System.Private.CoreLib, про які повідомлялося для шаблонного додатку iOS з: xamarin-macios#18629 та dotnetdotnet/runtime#91520.

-        У наступних випусках ми плануємо вирішити проблеми, пов'язані з фреймворком MAUI, та покращити загальний користувацький досвід. Наша мета — створити повністю сумісний з AOT та обрзкою фреймворк.

NET 8 буде підтримувати таргетинг платформ iOS з NativeAOT як опціональну функцію і демонструє великий потенціал, генеруючи на 50% менший і на 50% швидший запуск у порівнянні з Mono. Враховуючи високу продуктивність, яку обіцяє NativeAOT, будь ласка, допоможіть нам на цьому шляху і випробуйте свої додатки з NativeAOT та повідомляйте про будь-які потенційні проблеми. Водночас давайте нам знати, коли NativeAOT працює без проблем одразу.

Щоб стежити за подальшим прогресом, див. dotnetdotnet/runtime#80905. І останнє, але не менш важливе, ми хотіли б подякувати нашим учасникам GH, які допомагають нам зробити NativeAOT на iOS можливим.

Побудова та продуктивність внутрішнього циклу

Відфільтруйте вихідні дані Android ps -A за допомогою grep

При перегляді внутрішнього циклу Android для проєкту .NET MAUI з допомогою PerfView ми виявили, що близько 1,2% процесорного часу витрачається лише на отримання ідентифікатора процесу запущеного Android-додатку.

Змінивши багатослівність виводу на Diagnostics -  Tools > Options > Xamarin > Xamarin Diagnostics output , ви зможете побачити:

Розширення Xamarin/.NET MAUI у Visual Studio щосекунди опитує, чи не завершено роботу програми. Це корисно для зміни стану кнопки відтворення/зупинки, якщо ви примусово закриваєте програму тощо.

 

Тестуючи на Pixel 5, ми побачили, що команда насправді виводить 762 рядки!

Натомість ми могли б зробити щось на кшталт:

Де ми передаємо вивід ps -A до команди grep на пристрої Android. Так, Android має підмножину unix-команд! Ми фільтруємо або за рядком, що містить PID, або за назвою пакунка вашої програми.

 

В результаті тепер IDE розбирає лише 4 рядки:

Це не тільки оптимізує пам'ять, яка використовується для розділення та аналізу цієї інформації в C#, але adb також передає набагато менше байт через ваш USB-кабель або віртуально з емулятора.

Ця можливість з'явилася в останніх версіях Visual Studio 2022, що покращує цей сценарій для всіх користувачів Xamarin і .NET MAUI.

Перенесення використання vcmeta.dll з WindowsAppSDK на C#

 

Ми виявили, що кожна інкрементна збірка проєкту .NET MAUI, що працює під Windows, витрачає час:

Це компілятор XAML для WindowsAppSDK, який компілює XAML для WinUI3 (не .NET MAUI XAML). У проєктах .NET MAUI дуже мало XAML цього типу, фактично, єдиним файлом є файл Platforms/Windows/App.xaml у шаблоні проєкту.

 

Цікаво, що якщо в інсталяторі Visual Studio встановити Desktop development with C++ workload, то цей час просто зникне!

Компілятор XAML WindowsAppSDK звертається до власної бібліотеки з робочого навантаження C++, vcmeta.dll, щоб обчислити хеш для файлів збірки .NET. Це використовується для прискорення інкрементальних збірок — якщо хеш змінюється, компілюйте XAML заново. Якщо vcmeta.dll не було знайдено на диску, компілятор XAML фактично "перекомпілював все" при кожній інкрементальній збірці.

Для початкового виправлення ми просто включили невелику частину навантаження C++ як залежність .NET MAUI у Visual Studio. Дещо більший розмір інсталяції був гарним компромісом для економії до 4 секунд часу інкрементальної збірки.

 

Далі ми реалізували функціонал хешування vcmeta.dll звичайною мовою C# за допомогою System.Reflection.Metadata, щоб обчислювати ідентичні хеш-значення, як і раніше. Ця реалізація була не тільки кращою, оскільки ми могли позбутися залежності від робочого навантаження C++, але й швидшою! Час обчислення одного хешу:

Деякі з причин, чому це було швидше:

-       Не залучені p/invoke або COM-інтерфейси.

-        System.Reflection.Metadata має швидкий API на основі структур, що ідеально підходить для ітерацій над типами в .NET збірці та обчислення хеш-значення.

В результаті CompileXaml може бути навіть швидшим за 9 мс в інкрементних збірках.

 

Цю можливість було включено до WindowsAppSDK 1.3, який тепер використовується .NET MAUI у .NET 8. Докладні відомості про це вдосконалення див. у WindowsAppSDK#3128.

Покращення віддалених збірок iOS на Windows

Порівнюючи продуктивність внутрішнього циклу для iOS, було виявлено значний розрив між "віддаленою iOS" розробкою на Windows і локальною розробкою на macOS. Було зроблено багато невеликих удосконалень, заснованих на порівнянні файлів .binlog внутрішнього циклу, записаних на macOS, з файлами, записаними всередині Visual Studio на Windows.

Деякі приклади включають:

-        maui#12747: не копіювати явно файли на сервер збірки

-        xamarin-macios#16752: не копіювати файли на сервер збірки для операції видалення

-        xamarin-macios#16929: пакетне видалення файлів через DeleteFilesAsync

-        xamarin-macios#17033: кешувати шлях до компілятора AOT

-       Розширення Xamarin/MAUI Visual Studio: під час запуску dotnet-install.sh на віддалених хостах збірки встановіть явний прапорець процесора для комп'ютерів M1 Mac.

Ми також зробили деякі покращення для всіх проектів iOS та MacCatalyst, такі як:

-         xamarin-macios#16416: не обробляйте збірки знову і знову

Покращення внутрішнього циклу Android

Ми також зробили багато невеликих поліпшень у "внутрішній цикл" на Android  —  більшість з них були зосереджені на конкретній області.

Раніше проєкти Xamarin.Forms мали розкіш бути організованими в декілька проєктів, таких як:

-        YourApp.Android.csproj: Проєкт програми Xamarin.Android

-        YourApp.iOS.csproj: Проєкт додатку Xamarin.iOS

-        YourApp.csproj: бібліотека класів netstandard2.0

Де майже вся логіка програми Xamarin.Forms містилася в проекті netstandard2.0. Майже всі інкрементні збірки були б змінами до XAML або C# у бібліотеці класів. Така структура дозволила Xamarin.Android MSBuild-цілям повністю пропустити багато специфічних для Android кроків MSBuild. У .NET MAUI функція "єдиного проекту" означає, що кожна інкрементальна збірка повинна виконувати ці специфічні для Android кроки збірки.

Зосередившись саме на покращенні цієї сфери, ми внесли багато невеликих змін, таких як:

-        java-interop#1061: уникнення string.Format()

-        java-interop#1064: покращено ToJniNameFromAttributesForAndroid

-        java-interop#1065: уникнення перевірки File.Exists()

-        java-interop#1069: виправлено більше місць використання TypeDefinitionCache

-        java-interop#1072: використання меншої кількості System.Linq для користувацьких атрибутів

-        java-interop#1103: використання MemoryMappedFile при використанні Mono.Cecil

-        xamarin-android#7621: уникнення перевірки File.Exists()

-        xamarin-android#7626: покращено роботу LlvmIrGenerator.

-        xamarin-android#7652: швидкий шлях для <CheckClientHandlerType/>

-        xamarin-android#7653: затримка ToJniName під час генерації AndroidManifest.xml

-        xamarin-android#7686: ліниве заповнення пошуку ресурсів

Ці зміни мають покращити інкрементні збірки у всіх типах проектів .NET 8 для Android.

Компіляція XAML більше не використовує LoadInSeparateAppDomain

Переглядаючи звіт JITStats в PerfView (для MSBuild.exe):

Схоже, що Microsoft.Maui.Controls.Build.Tasks.dll проводив багато часу в JIT. Що було незрозуміло, так це те, що це була інкрементна збірка, де все вже повинно бути завантажено. Робота JIT вже повинна бути виконана?

Причиною є використання атрибута [LoadInSeparateAppDomain], визначеного за допомогою <XamlCTask/> у .NET MAUI. Це функція MSBuild, яка дозволяє завданням MSBuild запускатися в ізольованому AppDomain - з очевидним недоліком продуктивності. Однак, ми не могли просто видалити його, оскільки це призвело б до ускладнень...

[LoadInSeparateAppDomain] також зручно скидає весь статичний стан при повторному запуску <XamlCTask/>. Це означає, що майбутні інкрементні збірки потенційно використовуватимуть старі (сміттєві) значення. Існує декілька місць, які кешують об'єкти Mono.Cecil з міркувань продуктивності. Якщо цього не зробити, можуть виникнути дуже дивні помилки.

Для того, щоб зробити цю зміну, ми переробили весь статичний стан у компіляторі XAML, щоб він зберігався у полях та властивостях екземпляра. Це загальне покращення дизайну програмного забезпечення, на додаток до можливості безпечно видалити [LoadInSeparateAppDomain].

 

Результати цієї зміни для інкрементальної збірки на ПК з Windows:

Це дозволило заощадити близько 587 мс на інкрементних збірках на всіх платформах, що становить покращення на 82%. Це ще більше допоможе у великих рішеннях з декількома проєктами .NET MAUI, де <XamlCTask/> виконується декілька разів.

Дивіться maui#11982 для більш детальної інформації про це покращення.

Покращення продуктивності або розміру програми

Структури та IEquatable в .NET MAUI

 

За допомогою профілю Visual Studio .NET Object Allocation Tracking на прикладі клієнтського додатку .NET MAUI ми побачили:


Це здається непомірним обсягом пам'яті для запуску прикладу програми!

 

Заглибимось, щоб побачити, де ці структури були створені:

Основна проблема полягала в тому, що ця структура не реалізовувала IEquatable<T> і використовувалась як ключ для словника. Правило аналізу коду CA1815 було розроблено для виявлення цієї проблеми. Це правило не вмикається за замовчуванням, тому проєкти повинні вибрати його.

Щоб вирішити це:

-        Підписка є внутрішньою для .NET MAUI, і її використання дозволило зробити структуру доступною лише для читання. Це стало просто додатковим покращенням.

·        Ми зробили CA1815 помилкою збірки у всьому репозиторії dotnet/maui.

·        Ми реалізували IEquatable<T> для всіх типів struct.

Після цих змін ми більше не змогли знайти Microsoft.Maui.WeakEventManager+Subscription у знімках пам'яті взагалі. Що дозволило заощадити ~21 МБ розподіленої пам'яті у цьому прикладі програми. Якщо у ваших проєктах використовується struct, то варто зробити CA1815 помилкою збірки.

Меншу цільову версію цієї зміни було перенесено до MAUI у .NET 7. Докладні відомості про це покращення наведено у maui#13232.

Виправлено проблему продуктивності в {AppThemeBinding}

 

Аналізуючи зразок додатка .NET MAUI від клієнта, ми помітили багато часу, який витрачається на {AppThemeBinding} та WeakEventManager під час скролінгу:

У цьому додатку відбувалося наступне:

-        Стандартний шаблон проєкту .NET MAUI має багато {AppThemeBinding} у файлі Styles.xaml за замовчуванням. Це підтримка світлих та темних тем.

-        {AppThemeBinding} підписується на Application.RequestedThemeChanged

-        Отже, кожен перегляд MAUI підписується на цю подію - можливо, кілька разів.

-        Передплатники — це Dictionary<string, List<Subscriber>>, де відбувається пошук за словником, за яким слідує O(N) пошук операцій відписки.

Тут є потенційна можливість створити узагальнений шаблон "слабкої події" для .NET. Реалізація в .NET MAUI прийшла з Xamarin.Forms, але узагальнений шаблон може бути корисним для .NET розробників, які використовують інші фреймворки інтерфейсу користувача.

Щоб зробити цей сценарій швидким, поки що в .NET 8:

Раніше:

-        Для будь-якого {AppThemeBinding} він викликає обидва:

-        RequestedThemeChanged -= OnRequestedThemeChanged O(N) times

-       RequestedThemeChanged += OnRequestedThemeChanged постійний час

-       Де -= помітно повільніше, через, можливо, сотні підписників.

Після:

-        Створіть булеву функцію _attached, щоб ми знали "стан", чи вона приєднана, чи ні.

-        Нові прив'язки викликають лише +=, тоді як -= тепер викликатиметься {AppThemeBinding} лише у рідкісних випадках.

-        Більшість програм .NET MAUI не "скасовують" прив'язки, але -= буде використано лише у цьому випадку.

Повну інформацію про це виправлення див. в maui#14625. Див. dotnetdotnet/runtime#61517 про те, як ми можемо реалізувати "слабкі події" у .NET у майбутньому.

Зверніться до CA1307 та CA1309 для отримання інформації про продуктивність

 

Переглядаючи зразок додатка .NET MAUI від клієнта, ми помітили час, що витрачається на "культурно-орієнтовані" операції з рядками:

Цю ситуацію можна покращити, просто викликавши натомість ToLowerInvariant(). У деяких випадках ви можете навіть розглянути можливість використання string.Equals() з StringComparer.Ordinal. У цьому випадку наш код було додатково переглянуто та оптимізовано у статтях Зменшення  Java  взаємодії з  у  MauiDrawable  на  Android.

У .NET 7 ми додали правила аналізу коду CA1307 і CA1309 для виявлення подібних випадків, але, схоже, ми пропустили деякі з них у Microsoft.Maui.Graphics.dll. Ці правила можуть бути корисними для використання у ваших власних додатках .NET MAUI, оскільки уникнення всіх культурно-залежних операцій з рядками може мати значний вплив на мобільні пристрої.

Дивіться maui#14627, щоб дізнатися більше про це покращення.

Зверніться до CA1311 для отримання інформації

Після розгляду правил аналізу коду CA1307 і CA1309 ми пішли далі і розглянули CA1311.

 

Як згадувалося в турецькому  прикладі, подібні дії:

Можуть спричинити неочікувану поведінку в турецьких регістрах, оскільки в турецькій мові символ I (Юнікод 0049) вважається верхнім регістром іншого символу ý (Юнікод 0131), а i (Юнікод 0069) вважається нижнім регістром ще одного символу Ý (Юнікод 0130).

ToLowerInvariant() і ToUpperInvariant() також краще для продуктивності, оскільки інваріантна операція ToLower / ToUpper працює трохи швидше. Це також дозволяє уникнути завантаження поточної культури, що покращує продуктивність запуску.

 

Існують випадки, коли вам потрібно використовувати поточну культуру, наприклад, у випадку типу CaseConverter у .NET MAUI. Для цього вам просто потрібно чітко вказати, яку культуру ви хочете використовувати:

Мета цього CaseConverter - показати користувачеві текст у верхньому або нижньому регістрі. Тому має сенс використовувати для цього CurrentCulture.

Дивіться maui#14773, щоб дізнатися більше про це покращення.

Видалення невикористаної події ViewAttachedToWindow на Android

 

Кожен Label в .NET MAUI був підписаний:

Це залишилося після рефакторингу, але з'явилося у виводі дотнет-траси як:

Де перше — це підписка, а друге — подія, що викликається з Java на C# - тільки для запуску порожнього керованого методу.

 

Просто видаливши підписку на цю подію та порожній метод, ми залишили лише кілька елементів управління для підписки на цю подію за потреби:

Дивіться maui#14833, щоб дізнатися більше про це покращення.

Видаліть непотрібні System.Reflection для {Binding}

 

Всі прив'язки в .NET MAUI зазвичай потрапляють до шляху коду:

Де ~53% часу, витраченого на застосування прив'язки, з'явилося в dotnet-трасі в методі MethodInfo.GetParameters():

 

Вищенаведений код C# просто знаходить тип властивості. Він використовує обхідний спосіб використання першого параметра задавача властивості, який можна спростити:

Ми могли побачити результати цієї зміни в бенчмарку BenchmarkDotNet:

Де ++ позначає нові зміни.

Дивіться maui#14830 для більш детальної інформації про це покращення.

Використання StringComparer.Ordinal для словника та хеш-набору

 

Проаналізувавши зразок додатку .NET MAUI від клієнта, ми помітили, що 4% часу під час прокрутки витрачається на пошук у словнику:

Спостерігаючи за стеком викликів, деякі з них надходили з культурно-орієнтованого пошуку рядків у .NET MAUI:

      



  - microsoft.maui!Microsoft.Maui.PropertyMapper.GetProperty(string)

  -microsoft.maui!Microsoft.Maui.WeakEventManager.AddEventHandler(System.EventHandler<TEventArgs_REF>,string)

- microsoft.maui!Microsoft.Maui.CommandMapper.GetCommand(string)

Які відображаються в dotnet-trace у вигляді суміші рядкових порівнянь:

У випадку Dictionary<string, TValue> або HashSet<string> ми можемо використовувати StringComparer.Ordinal у багатьох випадках, щоб пришвидшити пошук у словнику. Це має дещо покращити продуктивність обробників та всіх елементів управління .NET MAUI на всіх платформах.

Дивіться maui#14900, щоб дізнатися більше про це покращення.

Зменшення взаємодії з Java у MauiDrawable на Android

 

Профілюючи зразок .NET MAUI клієнта під час скролінгу на Pixel 5, ми побачили, як цікаво він проводив час:

У цьому прикладі <Border/> знаходиться всередині <CollectionView/>, тому ви можете бачити, як це відбувається під час прокрутки.

 

Зокрема, ми розглянули код в .NET MAUI, такий як:

Це п'ять викликів з C# на Java. Створення нового методу в PlatformInterop.java дозволило нам скоротити його до одного разу.

 

Ми також покращили наступний метод, який виконує багато викликів з C# на Java:

Щоб бути більш лаконічно реалізованим на Java як:

 

Що зводить нашу нову реалізацію на стороні C# до одного виклику Java та створення структури Android.Graphics.Color:

Після цих змін ми побачили такий вивід dotnet-trace:

Це збільшує продуктивність будь-якого <Border/> (та інших фігур) на Android і зменшує використання процесора на ~1% під час прокрутки у цьому прикладі.

Дивіться maui#14933 для більш детальної інформації про це покращення.

Покращення продуктивності верстки Label на Android

 

Тестуючи різні зразки додатків .NET MAUI на Android, ми помітили, що близько 5,1% часу витрачається на PrepareForTextViewArrange():

 

Більшість часу витрачається на виклик Android.Views.View.Context, щоб потім мати змогу викликати метод розширення:

Виклик властивості Context може бути дорогим через взаємодію між C# та Java. Java повертає хендл на екземпляр, після чого нам доводиться шукати всі наявні керовані об'єкти C# для Context. Якщо всієї цієї роботи можна просто уникнути, це може значно підвищити продуктивність.

У .NET 7 ми зробили перевантаження для ToPixels(), що дозволяє отримати те саме значення за допомогою Android.Views.View

 

Тож замість цього ми можемо зробити так:

Ця зміна не тільки покращила результати dotnet-trace, але й помітно вплинула на наші LOLs  в  секунду у нашому тестовому додатку порівняно з минулим роком:

Дивіться maui#14980, щоб дізнатися більше про це покращення.

Зменшення викликів взаємодії Java для елементів керування в .NET MAUI

Огляд чудового прикладу .NET MAUI "Surfing App" від @jsuarezruiz:

 

Ми помітили, що багато часу витрачається на взаємодію з Java під час прокрутки:

Ці методи були глибоко вкладені, виконуючи взаємодію з Java -> C# -> Java на багатьох рівнях. У цьому випадку, переміщення деякого коду з C# на Java може призвести до того, що він буде виконувати менше операцій, а в деяких випадках взагалі не буде виконувати жодної операції!

 

Так, наприклад, раніше DispatchDraw() перевизначався у C#, щоб реалізувати поведінку відсікання:

 

Створивши PlatformContentViewGroup.java, ми можемо зробити щось на зразок

setHasClip() викликається, коли відсікання увімкнено/вимкнено у будь-якому елементі управління .NET MAUI. Це дозволило загальному шляху взагалі не взаємодіяти з C#, а лише з тими елементами управління, які ввімкнули відсікання. Це дуже добре, тому що dispatchDraw() викликається досить часто під час верстки Android, скролінгу тощо.

Таку саму обробку було також зроблено з кількома іншими внутрішніми типами .NET MAUI, такими як WrapperView: покращено загальну ситуацію, щоб взаємодія відбувалася лише тоді, коли перегляди вибрали відсікання або відкидання тіней.

 

Для тестування впливу цих змін ми використовували Google's FrameMetricsAggregator від Google який можна налаштувати в Platforms/Android/MainActivity.cs будь-якого додатка .NET MAUI:

API FrameMetricsAggregator є дещо дивним, але дані, які ми отримуємо, є досить корисними. Результатом є таблиця пошуку, де ключ — це тривалість в мілісекундах, а значення — кількість "кадрів", які зайняли цю тривалість. Ідея полягає в тому, що будь-який кадр, який триває довше 16 мс, вважається "повільним" або "смиканим", як іноді кажуть в документації до Android.

 

Приклад .NET MAUI "Surfing App", що працює на Pixel 5:

 

Після внесення змін до ContentViewGroup та WrapperView ми отримали дуже гарне покращення! Навіть у додатку, що інтенсивно використовує обрізки та тіні:

Перегляньте maui#14275 для більш детальної інформації про ці зміни.

Збільшення продуктивності Entry.MaxLength на Android

Досліджуємо зразок клієнта .NET MAUI:

-        Навігація з випадаючого вікна Shell.

-        На нову сторінку з кількома елементами керування введенням.

-        Була помітна затримка у виконанні.

 

Під час профілювання на Pixel 5 одним з “гарячих шляхів” був Entry.MaxLength:

-        Виклики EditTextExtensions.UpdateMaxLength()

-        Getter та setter EditText.Text

-        Виклики EditTextExtensions.SetLengthFilter()

-        EditText.Get/SetFilters()

В результаті ми пересилаємо рядки та IInputFilter[] між C# та Java для кожного елемента управління Entry. Всі елементи управління Entry проходять через цей шлях коду (навіть ті, що мають значення MaxLength за замовчуванням), тому є сенс перенести частину цього коду з C# на Java.

 

Наш код на C# раніше:

Натомість перейшли на Java (з ідентичною поведінкою):

Це дозволяє уникнути маршування (копіювання!) значень рядків і масивів з C# на Java і навпаки. Завдяки цим змінам виклики EditTextExtensions.UpdateMaxLength() стали настільки швидкими, що вони повністю відсутні у виводі dotnet-trace, заощаджуючи ~19 мс при переході на сторінку у клієнтському прикладі.

Дивіться maui#15614, щоб дізнатися більше про це покращення.

Зменшення використання пам'яті CollectionView на Windows

 

Ми розглянули зразок клієнта .NET MAUI з CollectionView на 150 000 прив'язаних до даних рядків. Налагоджуючи те, що відбувається під час виконання, .NET MAUI ефективно виконував:

А потім кожен елемент створюється в міру прокручування:

Це був не найкращий підхід, але для покращення ситуації:

-        використовуйте натомість  Dictionary<int, T>, просто дозвольте йому динамічно змінювати розмір.

-        використовуйте TryGetValue(..., out var context), щоб кожен виклик звертався до індексатора на один раз менше, ніж раніше.

-        використовуйте або розмір пов'язаної колекції, або 64 (залежно від того, що менше) як приблизну оцінку того, скільки зображень може поміститися на екрані за один раз

 

Наш код змінюється на:

Після внесення цих змін, знімок пам'яті програми після запуску наступний:

Що економить близько 1 МБ пам'яті при запуску. У цьому випадку краще просто дозволити Словнику самому визначати свій розмір з оцінкою того, якою буде його ємність.

Дивіться maui#16838, щоб дізнатися більше про це покращення.

Використовуйте UnmanagedCallersOnlyAttribute на платформах Apple

Коли некерований код викликає керований код, наприклад, виклик зворотного виклику з Objective-C, раніше в Xamarin.iOS, Xamarin.Mac і .NET 6+ для цієї мети використовувався атрибут [MonoPInvokeCallbackAttribute]. Атрибут [UnmanagedCallersOnlyAttribute] з'явився як сучасна заміна цієї функції Mono, яка реалізована з урахуванням продуктивності.

На жаль, є кілька обмежень при використанні цього нового атрибуту:

·        Метод повинен бути позначений як статичний.

·        Не можна викликати з керованого коду.

·        Повинні бути тільки аргументи, що розбиваються на частини.

·        Не повинен мати параметрів узагальненого типу або міститися в узагальненому класі.

Нам довелося не тільки рефакторити "генератор коду", який створює багато прив'язок для API Apple для AppKit, UIKit і т.д., але й багато ручних прив'язок, які потребували б такої ж обробки.

В результаті більшість функцій зворотного виклику з Objective-C на C# повинні працювати швидше в .NET 8, ніж раніше. Дивіться xamarin-macios#10470 та xamarin-macios#15783 для отримання детальної інформації про ці покращення.

Швидша взаємодія з Java для рядків на Android

При зв'язуванні членів, що мають типи параметрів або типів повернення java.lang.CharSequence, член "перевантажується" для заміни CharSequence на System.String, а "оригінальний" член має суфікс Formatted.

 

Наприклад, розглянемо android.widget.TextView який має функцію getText() та setText() методи, які мають типи параметрів та повертають типи java.lang.CharSequence:

У зв'язаному вигляді це призводить до двох властивостей:

 

"Неформатоване перевантаження" працює шляхом створення тимчасового об'єкта String для виклику форматованого перевантаження, ось так виглядає фактична реалізація:

TextView.Text набагато легше зрозуміти і простіше використовувати для .NET розробників, ніж TextView.TextFormatted.

Проблемою такого підходу є продуктивність: створення нового екземпляру Java.Lang.String вимагає:

1.         Створення керованого однорангового об'єкту (екземпляру Java.Lang.String),

2.         Створення нативного однорангового екземпляру (екземпляр java.lang.String),

3.        І реєстрація співвідношення між (1) і (2)

А потім одразу цим і користуйтесь ..

 

Це особливо помітно у додатках .NET MAUI. Розглянемо приклад клієнта, який використовує XAML для встановлення прив'язаних до даних значень Text  у CollectionView, які зрештою потрапляють до TextView.Text. Профілювання показує:

6.3% часу скролінгу витрачається на встановлення властивості TextView.Text!

 

Цей випадок можна частково оптимізувати: якщо член *Formatted є (1) властивістю і (2) не є віртуальним, то ми можемо безпосередньо викликати метод встановлювача Java.Це дозволяє уникнути необхідності створення керованого однорангового пристрою та реєстрації зв'язку між одноранговими пристроями:

В результаті чого:

Час виклику встановлювача властивості TextView.Text зменшено до 20% від попереднього середнього часу виклику.

Зауважте, що віртуальний випадок є проблематичним з інших причин, але, на щастя, TextView.setText() не є віртуальним і, ймовірно, є одним з найбільш поширених API Android.

Дивіться java-interop#1101 для більш детальної інформації про це покращення.

Швидша взаємодія з Java для подій C# на Android

 

Проаналізувавши вибірку клієнтів .NET MAUI під час прокрутки на Pixel 5, ми побачили ~2,2% часу, витраченого на конструктор IOnFocusChangeListenerImplementor, через підписку на подію View.FocusChange:

MAUI підписується на Android.Views.View.FocusChange для кожного подання, розміщеного на екрані, що відбувається під час прокрутки у цьому прикладі.

 

Переглядаючи згенерований код конструктора IOnFocusChangeListenerImplementor, ми бачимо, що він все ще використовує застарілі API JNIEnv:

Які ми можемо змінити, щоб використовувати новіші/швидші API Java.Interop:

Вони кращі, оскільки еквівалентний виклик JNIEnv.FindClass() кешується, серед іншого. Це був лише один з випадків, який ми випадково пропустили, коли впроваджували нові API Java.Interop в Xamarin. Нам просто потрібно було оновити наш генератор коду, щоб він видавав кращу прив'язку C# для цього випадку.

 

Після цих змін ми побачили натомість результати в dotnet-trace:

Це повинно покращити продуктивність усіх подій C#, які обгортають слухачів Java, шаблон дизайну, який зазвичай використовується у програмах на Java та Android. Сюди входить подія FocusedChanged, яка використовується всіма представленнями .NET MAUI на Android.

 

Дивіться java-interop#1105 для більш детальної інформації про це покращення.

Використання функціональних покажчиків для JNI

 

Існують різні механізми та згенерований код, які роблять можливим взаємодію Java з C#. Візьмемо, наприклад, наступний метод екземпляру foo() в Java:

 

Метод C# з назвою CallObjectMethod відповідає за виклик власного інтерфейсу Java (JNI), який викликає JVM для виклику методу Java:

 

У Xamarin.Android, .NET 6 та .NET 7 всі виклики на Java проходять через java_interop_jnienv_call_object_method_a p/invoke, сигнатура якого має такий вигляд:

Що реалізовано на мові C наступним чином:

C# 9 вводить функції вказівники  що дозволило нам дещо спростити роботу — і, як наслідок, пришвидшити її.

Отже, замість того, щоб використовувати p/invoke у .NET 8, ми могли б викликати новий небезпечний метод з назвою CallObjectMethodA:

Який викликає покажчик на функцію C# напряму:

Цей покажчик на функцію оголошено з використанням нового синтаксису, введеного в C# 9:

Порівняння двох реалізацій з ручним бенчмарком:

У Release-збірці середній час виклику JIFunctionPointersTiming займає 97% від часу JIPinvokeTiming, тобто виходить на 3% швидше. Крім того, використання вказівників на функції C# 9 означає, що ми можемо позбутися всіх функцій C java_interop_jnienv_*(), що зменшує libmonodroid.so на ~55 КБ для кожної архітектури.

Дивіться xamarin-android#8234 та java-interop#938 для більш детальної інформації про це покращення.

Видалено Xamarin.AndroidX.Legacy.Support.V4

 

Переглядаючи залежності .NET MAUI для Android, ми помітили підозрілий пакет:

Якщо ви знайомі з Бібліотеками Підтримки Android, це набір пакунків, які Google надає для "переливання" API у попередні версії Android. Це дає їм можливість додавати нові API до старих версій ОС, оскільки екосистема Android (OEM-виробники тощо) оновлюється набагато повільніше, ніж, наприклад, iOS. Цей конкретний пакет, Legacy.Support.V4, насправді підтримує Android аж до Android API 4! Мінімальна підтримувана версія Android в .NET - це Android API 21, яка була випущена в 2017 році.

Виявляється, ця залежність була перенесена з Xamarin.Forms і насправді не була потрібна. Як і очікувалося, ця зміна призвела до того, що з додатків .NET MAUI було видалено багато Java-коду. Настільки багато, що додатки .NET 8 MAUI тепер підпадають під ліміт мультидексів - весь байт-код Dalvik може зафіксувати в одному файлі classes.dex.

 

Детальна розбивка змін розміру за допомогою apkdiff:

Дивіться dotnetdotnet/maui#12232, щоб дізнатися більше про це покращення.

Дедуплікація генериків на iOS та macOS

У .NET 7 додатки для iOS збільшилися у розмірі через використання узагальнень C# у декількох збірках .NET. Коли моно AOT-компілятор .NET 7 зустрічає узагальнений екземпляр, який не обробляється спільним використанням, він видає код цього екземпляра. Якщо той самий екземпляр зустрічається під час AOT-компіляції у декількох збірках, код буде видано кілька разів, що збільшить розмір коду.

У .NET 8 нові опції командного рядка dedup-skip і dedup-include передаються компілятору Mono AOT. Створено нову збірку aot-instances.dll для спільного використання цієї інформації в одному місці у всій програмі.

Зміна була протестована в додатку MySingleView і тестах Monotouch в кодовій базі xamarin/xamarin-macios:

Дивіться xamarin-macios#17766 для більш детальної інформації про це покращення.

Виправлено реалізацію System.Linq.Expressions на iOS-подібних платформах

У .NET 7 кодові шляхи в System.Linq.Expressions контролювалися різними прапорцями, такими як:

-        CanCompileToil

-        CanEmitObjectArrayDelegate

-       CanCreateArbitraryDelegates

 

Ці прапорці керують кодовими шляхами, які є "дружніми до AOT", а які ні. Для десктопних платформ NativeAOT визначає наступну конфігурацію для AOT-сумісного коду:

Що стосується iOS-подібних платформ, то бібліотека System.Linq.Expressions була зібрана з увімкненим константним розмноженням та вилученими керуючими змінними. Це призвело до того, що перелічені вище перемикачі функцій NativeAOT не мали жодного ефекту (не обрізалися під час збирання програми), що потенційно могло призвести до того, що компіляція AOT йшла непідтримуваними шляхами коду на цих платформах.

У .NET 8 ми уніфікували збірку System.Linq.Expressions.dll, щоб забезпечити однакову збірку для всіх підтримуваних платформ і середовищ виконання, а також спростили ці перемикачі для врахування IsDynamicCodeSupported, щоб тример .NET міг видаляти відповідні IL в System.Linq.Expressions.dll під час збірки додатку.

Дивіться dotnetdotnet/runtime#87924 та dotnetdotnet/runtime#89308 для отримання детальної інформації про це покращення.

Встановіть DynamicCodeSupport=false для iOS та Catalyst

У .NET 8 перемикач функцій $(DynamicCodeSupport) встановлено у значення false для платформ:

-        Де неможливо публікувати без компілятора AOT.

-        Коли перекладач не ввімкнений.

Це стосується додатків, що працюють на iOS, tvOS, MacCatalyst тощо.

DynamicCodeSupport=false дозволяє тримеру .NET видаляти шляхи коду в залежності від RuntimeFeature.IsDynamicCodeSupported, наприклад цей  приклад  у  System.Linq.Expressions.

 

Орієнтовна економія становить:

У поєднанні з System.Linq.Expressions  на  iOS-подібних  платформах це дало гарне загальне покращення розміру програми:

Дивіться xamarin-macios#18555 для більш детальної інформації про це покращення.

Витоки пам'яті

Витоки пам'яті та якість

Враховуючи, що основною темою .NET MAUI в .NET 8 є якість, проблеми, пов'язані з пам'яттю, стали основною темою цього випуску. Деякі з виявлених проблем існували навіть у кодовій базі Xamarin.Forms, тому ми раді працювати над створенням фреймворку, на який розробники можуть покластися при створенні крос-платформних .NET додатків.

Більш детальну інформацію про роботу, виконану в .NET 8, можна знайти в різних прес-релізах та випусках, пов'язаних з проблемами пам'яті, за посиланням:

-        Запити

-        Проблеми

Ви можете бачити, що в .NET 8 був досягнутий значний прогрес в цій області.

Якщо порівняти .NET 7 MAUI з .NET 8 MAUI у прикладі додатку, що працює на Windows, виводячи результати виконання GC.GetTotalMemory() на екран:

Порівняння на Windows: .NET 7 проти .NET 8, зображення

Потім порівняйте приклад програми, що працює на macOS, але з набагато більшою кількістю сторінок у стеку навігації:

Порівняння на Mac: .NET 7 проти .NET 8, зображення

Дивіться приклад  коду  для  цього  проекту  на  GitHub для більш детальної інформації.

Діагностика витоків в .NET MAUI

Симптомом витоку пам'яті в .NET MAUI додатку може бути щось на кшталт цього:

-        Перейдіть з цільової сторінки на підсторінку.

-        Поверніться.

-        Знову перейдіть на підсторінку.

-        Повторіть.

-        Пам'ять постійно зростає, поки операційна система не закриє програму через нестачу пам'яті.

 

У випадку Android ви можете побачити такі повідомлення журналу, як

У цьому прикладі маса розміром 116 МБ є досить великою для мобільного додатку, а також понад 46 000 об'єктів обгортки C# <-> Java!

Щоб точно визначити, чи підсторінка втрачає, ми можемо зробити кілька модифікацій у додатку .NET MAUI:

 

1.         Додати реєстрацію у фіналізаторі. Наприклад:

Під час навігації по вашому додатку ви можете виявити, що цілі сторінки живуть вічно, якщо повідомлення журналу ніколи не відображається. Це поширений симптом витоку, оскільки будь-яке подання містить .Parent.Parent.Parent і т.д. аж до об'єкта Page.

 

2.      Викликати GC.Collect() десь у додатку, наприклад, у конструкторі підсторінки:

Це робить GC більш детермінованим, оскільки ми змушуємо його працювати частіше. Кожного разу, коли ми переходимо на підсторінку, ми з більшою ймовірністю спричиняємо зникнення старих підсторінок. Якщо все працює належним чином, ми повинні побачити повідомлення журналу від фіналізатора.

Зауважте, що GC.Collect() призначено лише для налагодження. Після завершення дослідження вам не знадобиться ця функція у вашому додатку, тому обов'язково видаліть її після завершення.

3.   Після внесення цих змін протестуйте релізну збірку вашого додатка.

На iOS, Android, macOS тощо ви можете переглядати консольний вивід вашого додатку, щоб визначити, що насправді відбувається під час виконання. adb  logcat наприклад, є способом перегляду цих логів на Android.

Якщо ви працюєте під Windows, ви також можете скористатися Debug > Windows > Diagnostic Tools у Visual Studio для створення знімків пам'яті у Visual Studio. У майбутньому ми хотіли б, щоб засоби діагностики Visual Studio підтримували програми .NET MAUI, що працюють на інших платформах.

Дивіться нашу вікі-сторінку про пам'яті витоки  wiki, для отримання додаткової інформації про витоки пам'яті у додатках .NET MAUI.

Патерни, що призводять до витоків: Події C#

Події C#, такі як поля, властивості тощо, можуть створювати сильні зв'язки між об'єктами. Розгляньмо ситуацію, коли все може піти не так.

 

Візьмемо, наприклад, кросплатформну властивість Grid.ColumnDefinitions:

-       Grid має сильне відношення на колекцію ColumnDefinitionCollection через BindableProperty.

-    ColumnDefinitionCollection має сильне відношення на Grid через подію ItemSizeChanged.

Якщо ви поставите точку зупинки на рядку з ItemSizeChanged +=, ви побачите, що подія має об'єкт EventHandler, де Target є сильним посиланням назад на Grid.

У деяких випадках такі циклічні посилання цілком прийнятні. Збирачі сміття середовища виконання .NET знають, як збирати цикли об'єктів, які вказують один на одного. Якщо немає "кореневого" об'єкта, який утримує обидва об'єкти, вони обидва можуть зникнути.

Проблема виникає з часом життя об'єктів: що станеться, якщо ColumnDefinitionCollection існуватиме протягом усього життя програми?

 

Розглянемо наступний Style у Application.Resources або Resources/Styles/Styles.xaml:

Якщо ви застосували цей стиль до сітки на довільній сторінці:

- Основний словник ресурсів програми містить стиль.

-  Стиль містить ColumnDefinitionCollection.

-  ColumnDefinitionCollection містить сітку.

-  На жаль, Grid утримує сторінку через .Parent.Parent.Parent і т.д.

Ця ситуація може призвести до того, що цілі сторінки будуть жити вічно!

Зауваження Проблему з Grid виправлено у maui#16145, але вона є чудовим прикладом ілюстрації того, як події C# можуть піти не так, як треба.

Кільцеві посилання на платформах Apple

Ще з перших днів існування Xamarin.iOS існувала проблема з "циклічними посиланнями", навіть у середовищі виконання, що збирає сміття, як .NET. Об'єкти C# співіснують зі світом посилань на платформах Apple, і тому об'єкт C#, який має підкласи NSObject, може потрапити в ситуацію, коли він випадково може жити вічно — витік пам'яті. Це не є специфічною проблемою .NET, оскільки ви можете так само легко створити таку ж ситуацію в Objective-C або Swift. Зверніть увагу, що цього не відбувається на платформах Android або Windows.

 

Візьмемо, наприклад, наступне кільцеве посилання:

У цьому випадку:

-  parent -> view через Subviews

-  view -> parent через властивість Parent

-  Кількість посилань на обидва об'єкти відмінна від нуля.

- Обидва об'єкти живуть вічно.

 

Ця проблема не обмежується полем або властивістю, ви можете створювати подібні ситуації з подіями C#:

У цьому випадку:

-  MyView -> UIDatePicker через Subviews

- UIDatePicker -> MyView через ValueChanged та EventHandler.Target

- Обидва об'єкти живуть вічно.

Рішення для цього прикладу — зробити метод OnValueChanged static, що призведе до значення null Target в екземплярі EventHandler.

 

Іншим рішенням може бути розміщення OnValueChanged у підкласі, який не є NSObject:

Це шаблон, який ми використовуємо у більшості обробників .NET MAUI та інших підкласах UIView.

Подивіться на MemoryLeaksOniOS якщо ви хочете ізольовано погратися з деякими з цих сценаріїв у додатку для iOS без .NET MAUI.

Аналізатор Roslyn для платформ Apple

 

Також у нас є експериментальний  аналізатор Roslyn, який може виявляти такі ситуації під час збірки. Щоб додати його до проєктів net7.0-ios, net8.0-ios тощо, ви можете просто встановити пакет NuGet:

Деякі приклади попередження можуть бути наступними:

Зауважте, що аналізатор може попередити про можливу проблему, тому його ввімкнення у великій наявній кодовій базі може бути досить шумним. Перевірка пам'яті під час виконання — найкращий спосіб визначити, чи дійсно є витік пам'яті.

Інструменти та документація

Спрощені dotnet-trace та dotnet-dsrouter

У .NET 7 профілювання мобільних додатків було дещо складним завданням. Вам потрібно було запустити dotnet-dsrouter і dotnet-trace разом і виконати всі налаштування правильно, щоб мати змогу отримати .nettrace або speedscope для дослідження продуктивності. Також не було вбудованої підтримки dotnet-gcdump для підключення до dotnet-dsrouter для отримання знімків пам'яті запущеної програми .NET MAUI.

У .NET 8 ми спростили цей сценарій, створивши нові команди для dotnet-dsrouter, які спрощують робочий процес.

 

Щоб переконатися, що у вас встановлені найновіші діагностичні засоби, ви можете встановити їх за посиланням:

Переконайтеся, що у вас встановлені версії цих інструментів не нижче 8.x:

 

Щоб профілювати Android-додаток на емуляторі Android, спочатку створіть і встановіть свій додаток у режимі Release, наприклад, так:

Далі відкрийте термінал для запуску dotnet-dsrouter

 

Потім у другому вікні терміналу ми можемо встановити системну властивість debug.mono.profile Android, як замінник $DOTNET_DiagnosticPorts:

Зауважте, що Android не має належної підтримки змінних оточення, таких як $DOTNET_DiagnosticPorts. Ви можете створити текстовий файл AndroidEnvironment  для встановлення змінних середовища, але системні властивості Android можуть бути простішими, оскільки для їх встановлення не потрібно перезбирати програму.

Після запуску програми для Android вона повинна мати можливість підключитися до dotnet-dsrouter -> dotnet-trace і записати інформацію про профілювання продуктивності для дослідження. Аргумент --format є необов'язковим і за замовчуванням має значення .nettrace. Однак файли .nettrace можна переглянути лише за допомогою Perfview у Windows, тоді як JSON-файли speedscope можна переглянути "на" macOS або Linux, завантаживши їх на https://speedscope.app.

Зауваження Якщо ви надаєте ідентифікатор процесу програмі dotnet-trace, вона знає, як визначити, чи є ідентифікатор процесу dotnet-dsrouter, і з'єднатися через нього належним чином.

dotnet-dsrouter має наступні нові команди для спрощення робочого процесу:

-  dotnet-dsrouter android: Пристрої Android

- dotnet-dsrouter android-emu: Емулятори Android

- dotnet-dsrouter ios: пристрої iOS

- dotnet-dsrouter ios-sim: симулятори iOS

Дивіться вікі .NET MAUI для отримання додаткової інформації про профілювання додатків .NET MAUI на кожній платформі.

Підтримка мобільних пристроїв dotnet-gcdump 

У .NET 7 у нас був дещо складний метод (див.  вікі) для отримання знімка пам'яті програми у середовищі виконання Mono (наприклад, iOS або Android). Вам потрібно було використовувати спеціальний для Mono провайдер подій, наприклад:

А потім ми поклалися на Філіпа Навару (Filip Navara) та його інструмент  mono-gcdump (дякуємо Філіпу!), щоб перетворити файл .nettrace у .gcdump, який можна відкрити у Visual Studio або PerfView.

 

У .NET 8 ми тепер маємо dotnet-gcdump для мобільних сценаріїв. Якщо ви хочете отримати знімок пам'яті запущеної програми, ви можете використовувати dotnet-gcdump так само як і dotnet-trace:

Зауваження Для цього потрібні такі самі налаштування, як і для dotnet-trace, наприклад, -p:AndroidEnableProfiler=true, dotnet-dsrouter, команди adb тощо.

 

Це значно спрощує наш робочий процес дослідження витоків пам'яті в додатках .NET MAUI. Дивіться нашу  wiki вікі-сторінку про витоки пам'яті    для отримання додаткової інформації.

 

Source






Posted on 18. October 2023

Announcing .NET MAUI in .NET 8 Release Candidate 2: More Quality

Анонс .NET MAUI у .NET 8 Release Candidate 2: Більше Якості


Сьогодні ми робимо ще один крок на зустріч до загального доступу до .NET 8 (GA), надаючи .NET MAUI у версії 2 (RC2) .NET 8. Як і RC1, на цей випуск поширюється ліцензія на запуск, тому ви можете отримати підтримку під час використання його у своїх робочих програмах. У цьому релізі ми зосередилися на проблемах, які регресували під час попереднього перегляду, і відновили деяку продуктивність, яку було втрачено, коли ми покращили надійність гарячого перезавантаження, візуального менеджера стану, прив’язки та тем додатків.

Покращення якості

 

На додаток до нашого звуженого фокуса на проблемах, ми також збільшили кількість ручних тестів і автоматизованих тестів. Між .NET 7 і .NET 8 немає змін в API, тому ви можете очікувати, що оновлення для ваших програм у цьому плані пройде гладко. Щоб дізнатися більше про оновлення з 7 до 8, дотримуйтеся цього простого посібника .


Основні моменти з цього релізу:


Покращення продуктивності: було зроблено кілька покращень продуктивності, зокрема покращено продуктивність ActivityExtensions.GetWindowFrame на Android і продуктивність «Setter Specificity». Ці оптимізації сприяють плавній роботі програми. (#17241 , #17364 , #17230 , #17505 , #17545).

 

 

Виправлення інтерфейсу користувача та елементів керування: було внесено кілька виправлень і оновлень до елементів керування та елементів інтерфейсу користувача, зокрема виправлення, пов’язані з CollectionView, видимістю TabBar, межами RoundRectangle і вирівнюванням тексту Android. Завдяки цьому інтерфейс вашого додатка є більш узгодженим і візуально точнішим на різних платформах. (#16870 , #17240 , #17261 , #17353 , #17430 , #17594, #17567).

 

Спеціалізовані виправлення для платформ: було внесено кілька специфічних  виправлень для платформ, зокрема функцію перетягування, зовнішній вигляд панелі вкладок і певну поведінку платформи, що забезпечує узгоджену взаємодію користувачів на різних платформах. (#15748 , #16561 , #17495 , #17041 , #17358).


Реліз також містить численні виправлення помилок, покращення та внески. Перегляньте повні примітки до випуску, щоб дізнатися більше.

Додаткова інформація:


- Примітки до релізу .NET MAUI

- .NET для Android

 

- .NET для iOS і Mac

 

Бонус: Реліз Сервісу .NET 7

Сьогодні ми також надіслали 8 реліз  сервісу .NET MAUI (версія 7.0.96) для .NET 7, включаючи вибрані високопріоритетні виправлення макета, витоків пам’яті, CollectionView, безпечної зони тощо. Ви можете скористатися цією версією служби, інсталювавши .NET 8 RC2 одним із наведених нижче методів і продовживши створювати свої програми для .NET 7.


Крім того, ви можете отримати 7.0.96, оновившись до Visual Studio 17.7.5.

Бонус 2: Xcode 15 та Android API 34

 

Тепер розробники Xamarin можуть використовувати Xcode 15 для націлювання на останні версії (наприклад, iOS 17, iPadOS 17) і націлювати Android API 34 , щоб відповідати політикам магазину. Для цього встановіть Visual Studio 17.8 Preview 3 або останню стабільну версію Visual Studio для Mac і налаштуйте середовище, як зазвичай. Це не надає нових API для платформи, але дозволяє продовжувати створення наявних проєктів, поки ви завершите оновлення до .NET 8 і .NET MAUI, незалежно від дати завершення підтримки Xamarin наступного року .

Як оновити

На всіх платформах ви можете розробляти з .NET MAUI за допомогою Visual Studio Code. Установіть розширення .NET MAUI і повідомте нам, як ми можемо покращити це прев’ю для вас у майбутньому.


Завантажте програму встановлення .NET 8 RC2 , а потім інсталюйте .NET MAUI з командного рядка:

 

dotnet workload install maui

 

Після припинення використання Visual Studio для Mac наступного року ви зможете продовжувати розробку за допомогою Visual Studio для Mac після ввімкнення функції попереднього перегляду для .NET 8 у параметрах.

 

Зворотний зв'язок

Ми цінуємо ваші відгуки та внески в .NET MAUI. Ви можете повідомляти про проблеми , пропонувати функції або  надсилати pull-запити в нашому репозиторії GitHub. Ви також можете приєднатися до нашого сервера Discord або підписатися на нас у Twitter, щоб бути в курсі останніх новин і оновлень.


Дякуємо всім 23 учасникам (і ботам), які допомогли створити цей випуск!


Дякуємо за підтримку та щасливого кодування!


У Windows оновіть або встановіть Visual Studio 2022 17.8 preview 3, щоб отримати .NET 8 RC2 із .NET MAUI (і 7.0.96).

 

Source




Posted on 9. July 2023

У .NET Community Toolkit 8.2.1 з’явилися покращені генератори вихідного коду та засоби виправлення коду!

 

Ми раді повідомити про офіційний запуск версії 8.2.1 .NET Community Toolkit! Ця нова версія містить багато покращень QoL у всіх бібліотеках, ще кілька оптимізацій продуктивності для генераторів джерел MVVM Toolkit, нові засоби виправлення коду та покращену діагностику тощо!


.NET Community Toolkit 8.2.1

Ми хочемо висловити особливу подяку всім членам спільноти, які надали цінні відгуки, щоб допомогти визначити пріоритетність завдань для цього нового випуску. Ваші внески та звіти про помилки допомагають нам робити .NET Community Toolkit ще кращим із кожним випуском — ви найкращі!

Що входить до складу .NET Community Toolkit?

.NET Community Toolkit містить такі бібліотеки:

CommunityToolkit.Common

CommunityToolkit.Mvvm(він же «Microsoft MVVM Toolkit»)

CommunityToolkit.Diagnostics

CommunityToolkit.HighPerformance

Щоб дізнатися більше про історію .NET Community Toolkit, ось посилання на нашу попередню публікацію оголошення про 8.0.0 .

Ось розбивка основних змін, які включені в цей новий випуск 8.2.1 .NET Community Toolkit. Цей випуск здебільшого зосереджений на поступових покращеннях: немає нових функцій, але є багато налаштувань і виправлень!

Новий аналізатор і коректор коду для[RelayCommand] 

Атрибут [RelayCommand] (див. документацію тут) може автоматично обробляти асинхронні методи, і в цьому випадку він використовуватиме інтерфейси IAsyncRelayCommand (разом із відповідним типом асинхронної команди). Однак розробникам було нелегко виявити цю функцію, і багато хто натомість створював свої командні методи. Це також означало, що вони не могли використовувати всю додаткову функціональність, надану асинхронними командами (наприклад, звітування про прогрес і контроль паралельності).

Щоб допомогти з цим, версія 8.2.1 MVVM Toolkit постачається з абсолютно новим аналізатором, який випромінює діагностику для методів async void , позначених [RelayCommand]. А щоб зробити роботу ще простішою, є також новий засіб виправлення коду, який автоматично перероблятиме код за вас — просто клацніть піктограму лампочки, і дозвольте Roslyn зробити роботу за вас!

Виправлення коду аналізатора MVVM Toolkit

 

Тут ви можете побачити нову згенеровану діагностику, яка відображається для методу async void, пов’язаного з командою, і відповідного інтерфейсу коректора коду у Visual Studio з попереднім переглядом змін. Він також автоматично додасть необхідний оператор using у верхній частині вашого файлу, якщо Task ще немає в області видимості. І так само, як і інші засоби виправлення коду в MVVM Toolkit, ви також можете легко застосувати його до всіх місць у всьому вашому проєкті чи рішенні одним клацанням миші!

Інші зміни та вдосконалення

Виправлено аварійну ситуацію при індексації розрізаного екземпляра Memory2D<T> (#675): у деяких випадках могло бути викликано порушення доступу під час індексування елементів після нарізання екземпляра Memory2D<T>. Тепер це виправлено, дякуємо mahalex за повідомлення про це!

– Виправлено атрибути пересилання з від'ємними значеннями переліку (#681): використання елементів переліку з від’ємними значеннями більше не спричиняє проблеми з генераторами MVVM Toolkit для згенерованих спостережуваних властивостей. Дякуємо n-coelho-cerinnov за повідомлення про це!

Виправлено збій генератора під час пересилання недійсних атрибутів (#683): спроба переслати атрибути, на які є неправильні посилання, тепер завершуватиметься помилкою та створюватиме зрозуміле повідомлення про помилку.

Виправлення генератора  ObservableValidator для виявлення успадкованих властивостей (#616): генератор для перевірки властивостей більше не буде випадково ігнорувати властивості базових типів для цільової моделі перегляду. Дякуємо dgellow за повідомлення про це!

Додано попередження під час використання packages.config для MVVM Toolkit (#695): генератори набору інструментів MVVM працюють лише під час використання <PackageReference>(це відоме обмеження SDK, і воно є задумом), але раніше не було чітких вказівок на те, чому генератори не працювали для користувачів, які намагаються використовувати їх із проекту за допомогою packages.config. MVVM Toolkit тепер постачається з покращеною діагностикою, яка створить корисне попереджувальне повідомлення в цьому випадку. Дякуємо, smaugbend , що повідомили про це!

Частіше перевіряйте скасування в генераторах (#703): це має призвести до невеликих покращень у чутливості IDE під час використання MVVM Toolkit.

 

Видалення непотрібного тимчасового розподілу масиву (#719): ще одна невелика оптимізація пам’яті для генераторів джерел MVVM Toolkit.

Обробка поля [ObservableProperty] з ідентифікаторами ключових слів (#710): генератор більше не створюватиме недійсний код у випадку, якщо поля анотовані [ObservableProperty] використовують ідентифікатори ключових слів, які були екрановані у джерелі (наприклад, @event). Дякуємо Get0457 за повідомлення про це!

 

Примітка: існує відома проблема з джерельними генераторами в старіших версіях Roslyn, через яку IntelliSense іноді може не працювати належним чином для згенерованих учасників (див. #493 і пов’язану проблему відстеження Roslyn). Це нарешті виправлено у VS 2022 17.7, який зараз знаходиться в прев’ю. Якщо ви бачите будь-які проблеми під час використання MVVM Toolkit, обов’язково спробуйте останню версію VS 17.7 Preview!

Інші зміни

Ви можете переглянути повний журнал змін для цього випуску на сторінці випуску GitHub .

Почніть сьогодні!

Ви можете знайти весь вихідний код у нашому репо GitHub , деякі рукописні документи на MS learn і повні посилання на API на веб-сайті браузера .NET API. Якщо ви хочете внести свій внесок, не соромтеся відкривати питання або зв’язуватися з нами, щоб повідомити про свій досвід! Щоб стежити за розмовою в Twitter, використовуйте хештег #CommunityToolkit. Усі ваші відгуки дуже допомагають у формуванні напрямків цих бібліотек, тож поділіться ними!

 

Щасливого кодування!

Source




Posted on 30. April 2023

Анонсуємо .NET Community Toolkit 8.2! Покращена швидкість роботи генераторів, засоби для усунення помилок у коді, збільшення продуктивності та багато іншого!

 

 

Ми раді повідомити про офіційний запуск версії 8.2 інструментарію .NET Community Toolkit! Ця нова версія містить покращення швидкості роботи як під час виконання, так і в генераторах вихідного коду MVVM Toolkit, нові засоби для усунення помилок, що підвищують вашу результативність, нові функції на основі запитів користувачів та багато іншого!

.NET Community Toolkit 8.1.0 Preview 1

Що входить до інструментарію .NET Community Toolkit? 👀

Інструментарій .NET Community Toolkit містить наступні бібліотеки:

  • CommunityToolkit.Common

  • CommunityToolkit.Mvvm (також відомий як "Microsoft MVVM Toolkit")

  • CommunityToolkit.Diagnostics

  • CommunityToolkit.HighPerformance

Ці компоненти також широко використовуються в деяких програмах для роботи з вхідними повідомленнями, які постачаються з Windows, зокрема у Microsoft Store і програма "Photos"! 🚀

Для більш детальної інформації про історію розвитку інструментарію .NET Community Toolkit, ось посилання на попередній пост з анонсом версії 8.0.0.

 

Перелік основних змін, які включені в нову версію 8.2 інструментарію .NET Community Toolkit.

Користувацькі атрибути для [RelayCommand] 🤖

Продовжуючи роботу, виконану у випуску 8.1.0, і як було запропоновано на GitHub, новий випуск 8.2.0 набору інструментів MVVM Toolkit містить підтримку користувацьких атрибутів при використанні [RelayCommand]. Знову ж таки, було використано нативне field: і property: C#, щоб вказати цільові значення користувацьких атрибутів. Завдяки цьому ви тепер маєте повний контроль над атрибутами для всіх згенерованих членів, коли використовуєте [RelayCommand] для створення команди MVVM.

Наприклад, це особливо корисно, коли ви використовуєте модель подання, яка має підтримувати серіалізацію JSON, і вам потрібно явно ігнорувати згенеровану властивість. Ви можете використовувати підтримку нового  field: і property: наступним чином:

Після цього будуть створені наступні елементи:

Як і слід було очікувати, згенерована властивість DoWorkCommand має вказаний атрибут над нею! І, звичайно ж, підтримуються атрибути з будь-якою кількістю конструкторів та іменованих параметрів. Ви також можете використовувати просто field:, property:  поле:або будь-яку їх комбінацію 🙌

Ви можете знайти всі документи про нові генератори вихідних кодів тут, а якщо ви віддаєте перевагу відеоверсії, Джеймс Монтемагно також зробив кілька відео про них, наприклад, це.

Нові змінені перехоплення [ObservableProperty] ⚗️

Відносно поширеним сценарієм у MVVM є наявність деякої властивості "вибраний елемент", яка представляє, наприклад, поточного вибраного користувача або вкладену модель представлення. Коли значення цієї властивості змінюється, нерідко доводиться вносити певні корективи до старого та нового екземплярів. Наприклад, встановити якусь "вибрану" властивість, або підписатися на подію, і так далі.

Раніше це був сценарій, де використання [ObservableProperty] не було ідеальним, оскільки воно не мало необхідної інфраструктури, щоб легко впровадити таку логіку для виконання необхідних змін стану для старих і нових значень, що встановлюються. Щоб виправити це, починаючи з версії 8.2 MVVM Toolkit, для всіх полів [ObservableProperty] генеруються два нові змінені перехоплення властивостей.

 

Наприклад, розглянемо наступний код:

Тепер буде згенеровано такий код:

Зверніть увагу на два нові методи "OnPropertyNameChanging" і "Changed", що генеруються, тепер вони також приймають попереднє значення. Ці два методи є простими у використанні перехопленнями для додавання коду, який спрацьовує при кожній події зміни властивості й може змінювати як старе, так і нове значення, що встановлюється. Наприклад, ви можете використовувати їх наступним чином:

І це все, що вам потрібно! Вибрана модель перегляду тепер завжди буде коректно повідомлятися як вибрана. Вам більше не потрібно повертатися до використання ручної властивості у подібних сценаріях, [ObservableProperty] тепер має вбудовану підтримку і для цього! 🪄

Примітка: MVVM Toolkit автоматично визначить, чи використовуєте ви будь-який з цих методів, щоб максимально оптимізувати кодову структуру. Крім того, виклики методів, які не реалізовані, будуть просто видалені компілятором Roslyn, тому вся ця функція є повністю платною!

Фіксери коду MVVM Toolkit 📖

У попередньому випуску MVVM Toolkit було додано два нових діагностичних аналізатора, які видають попередження при некоректному доступі до поля, позначеного [ObservableProperty], а також при оголошенні типу з [ObservableProperty] і подібними атрибутами, коли доступне використання наслідування. У версії 8.2 ці два аналізатори також містять вбудовані засоби для виправлення коду!

Тобто, коли будь-який з них видає попередження, ви можете просто навести курсор на лампочку IntelliSense, вибрати виправлення коду й автоматично застосувати всі необхідні зміни, щоб повернути ваш код до правильного вигляду! Вони також підтримують групові виправлення, тому ви можете виправити всі помилки одним клацанням! ✨

MVVM Toolkit analyzer code fix

Тут ви можете побачити новий інтерфейс виправлення коду у Visual Studio з попереднім переглядом змін, а також опціями застосування виправлення до потрібного вам діапазону

Оптимізація генератора вихідного коду MVVM Toolkit 🛫

Як і кожен випуск, MVVM Toolkit 8.2 також включає деякі покращення продуктивності генераторів вихідних кодів. Цього разу основна увага була приділена оптимізації інкрементних конвеєрів, щоб мінімізувати використання пам'яті й гарантувати, що жодні непотрібні об'єкти не залишаться активними під час паралельних виконань. Ось деякі зміни, які було зроблено для покращення цього:

  • Перенесено решту діагностик до аналізаторів (#581): ще дві діагностики з MVVM Toolkit було перенесено до діагностичного аналізатора, який можна запускати паралельно та поза процесом. Це вилучає деякі символи Roslyn з інкрементального конвеєра та покращує загальну продуктивність генератора.

  • Попередня обробка символів на початку роботи аналізаторів (#587): усі необхідні символи аналізатора тепер обробляються під час початкового налаштування зворотного виклику, що пришвидшує його виконання у кожному екземплярі компіляції.

Інші зміни та покращення 🚀

  • Виправлено помилку збірки з VB.NET проєктів (#592): MVVM Toolkit спричиняв помилки збірки з VB.NET проєктів через деякі некоректні властивості MSBuild. Наразі це виправлено.

  • Виправлено перенаправлені параметри подвійних атрибутів (#603): перенаправлені атрибути через [ObservableProperty] некоректно відображали цілі значення типів float та double у тип int. Тепер вони передаватимуться коректно зі збереженням початкового типу.

  • Виправлено генератори вихідного коду, що обробляють вкладені/загальні типи (#606): виправлено проблему, яка призводила до збою декількох генераторів вихідного коду при використанні Roslyn 4.0 та загальних типів.

  • Додано API ArrayPoolBufferWriter<T>.DangerousGetArray() (#616): цей новий API дозволяє легко взаємодіяти між ArrayPoolBufferWriter<T> та старими API, які вимагають масив T[] як параметр (на відміну від Span<T>/Memory<T>).

  • Вилучено System.Linq з CommunityToolkit.Diagnostics (#622): за результатами дослідження, проведеного у runtime/#82607, з пакунка Diagnostics повністю вилучено всі посилання на System.Linq. Це покращує підтримку обрізання у збірці та дозволяє заощаджувати більший розмір двійкових файлів у опублікованих збірках (особливо з NativeAOT).

  • Підтримка часткових методів з [RelayCommand] (#633): атрибут [RelayCommand] тепер працюватиме коректно, якщо його буде додано над визначенням або частиною реалізації часткового методу.

  • Додано підтримку відкритих узагальнених типів у ToTypeString (#639): розширення Type.ToTypeString() тепер коректно обробляє відкриті узагальнені типи. Наприклад, typeof(List<>).ToTypeString() тепер повертатиме "System.Collections.Generic.List<>".

  • Додано [MemberNotNull] у встановлювачах [ObservableProperty] (#646): коли це застосовано (тобто коли атрибут є доступним і тип властивості не можна занулити), генератор [ObservableProperty] також генеруватиме необхідні анотації про можливість занулення, щоб гарантувати, що встановлення створеної властивості коректно позначить поля як ініціалізовані. Це розв'язує проблему полів, які показували попередження про недопустимість, навіть якщо згенеровану властивість було встановлено.

  • Повні XML-документи для згенерованих членів (#653): усі згенеровані типи та члени тепер оформлено у вигляді повних XML-документів, тож перевірка коду, створеного генераторами вихідного коду MVVM Toolkit, має бути дещо простішою, ніж раніше.

Примітка: у старих версіях Roslyn існує відома проблема з генераторами вихідних кодів, через яку IntelliSense може іноді працювати некоректно для згенерованих елементів (див. #493 і пов'язану з ним проблему відстеження у Roslyn). Ця проблема має бути в основному виправлена в VS 2022 17.6 і вище (або, коли використовується Roslyn 4.6, в тому числі через інші IDE, такі як VS Code і Rider). Якщо ви зіткнулися з цією проблемою, переконайтеся, що ви оновили свій інструментарій до останньої доступної версії.

Інші зміни ⚙️

Ви можете переглянути повний список змін до цього випуску на сторінці релізу на GitHub.

Почніть вже сьогодні! 🎉

Ви можете знайти весь вихідний код у репозиторії GitHub, деякі рукописні документи на MS learn та повні посилання на API на вебсайт браузера .NET API. Якщо ви хочете зробити свій внесок, не соромтеся залишати проблеми або звертатися до команди, щоб повідомити про свій досвід! Щоб стежити за обговоренням у Twitter, використовуйте хештег #CommunityToolkit. Всі ваші відгуки дуже допомагають формувати напрямок розвитку цих бібліотек, тому обов'язково діліться ними!

 

Вдалого кодування! 💻



Posted on 5. February 2023

Відтворення аудіо та відео в додатках .NET MAUI за допомогою нового MediaElement

Відтворення аудіо та відео в додатках .NET MAUI за допомогою нового MediaElement

 

Вийшов один з найбільш очікуваних елементів управління для .NET MAUI - MediaElement. За допомогою MediaElement ви можете легко відтворювати аудіо та відео з вашого додатку .NET MAUI. В цій статті ви дізнаєтеся все, що вам потрібно знати про цю першу версію і про плани на майбутнє! Media Element є частиною .NET MAUI Community Toolkit, бібліотеки, створеної спільнотою, яка підтримується чудовими розробниками з усього світу, як з боку спільноти, так і з боку корпорації Майкрософт.

 

Що таке MediaElement?

З MediaElement ви отримуєте потужний елемент керування, який дозволяє відтворювати мультимедійні дані у вашому додатку .NET MAUI.


Можливо, ви вже знайомі з MediaElement з інструментарію спільноти Xamarin, куди його додали завдяки чудовій роботі учасника спільноти Пітера Фута. Хоча та версія була вже досить непоганою, вона також мала місце для вдосконалення, особливо на Android.


Саме тому, при перенесенні MediaElement на .NET MAUI, ми перебудували все з нуля. Таким чином, ми змогли зберегти всі ті частини, які вже є хорошими, і в той же час покращити ті речі, які потребують доопрацювання.

 

Під капотом

Для Android ми вирішили використовувати ExoPlayer як аналог платформи, замінивши Android MediaPlayer, який ми використовували для Xamarin. Таким чином, ми автоматично отримуємо багато додаткових функцій, які доступні нам з коробки, наприклад, відтворення HTTP-відео в прямому ефірі (HLS), чудові елементи керування транспортуванням платформи та багато іншого.


На iOS та macOS ми використовуємо платформу AVPlayer, як і для MediaElement в Xamarin. Також без змін залишився Tizen-плеєр, який використовує Tizen.Multimedia.Player.


Тепер, коли .NET MAUI будується на основі WinUI, а не UWP, ми використовуємо новий елемент MediaPlayerElement WinUI. Хоча цей елемент керування також є дуже молодим для WinUI, він вже є дуже повним і виглядає багатообіцяючим.

Підтримка різних медіаформатів відрізняється на різних платформах (і, можливо, залежно від того, які кодеки ви встановили), але, використовуючи нативні медіаплеєри платформи, для кожної операційної системи ми використовуємо всю потужність і пов'язану з цим оптимізовану продуктивність.

 

Початок роботи

Почати роботу з MediaElement дуже просто. По-перше, вам потрібно встановити пакет CommunityToolkit.Maui.MediaElement NuGet. Це окремий пакунок від основного пакунка Community Toolkit.


Після завершення встановлення перейдіть до вашого MauiProgram.cs і додайте наступний рядок ініціалізації до MauiAppBuilder:


public static MauiApp CreateMauiApp()

{

    var builder = MauiApp.CreateBuilder();

    builder

        .UseMauiApp<App>()

        // Initialize the .NET MAUI Community Toolkit MediaElement by adding the below line of code

        .UseMauiCommunityToolkitMediaElement()

        // After initializing the .NET MAUI Community Toolkit, optionally add additional fonts, and other things

        .ConfigureFonts(fonts =>

        {

            fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");

            fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");

        });


    // Continue initializing your .NET MAUI App here


    return builder.Build();

 

}


Тепер ви готові почати використовувати MediaElement у своєму додатку! Простий приклад у XAML можна знайти нижче.

 

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"

             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"

             xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"

             x:Class="MediaElementDemos.GettingStarted"

             Title="MediaElement Getting Started">


    <toolkit:MediaElement x:Name="mediaElement"

                      ShouldAutoPlay="True"

                      ShouldShowPlaybackControls="True"

                      Source="https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"

                      HeightRequest="300"

                      WidthRequest="400"

                      ... />

</ContentPage>

 

Це додасть елемент управління MediaElement на сторінку, яка почне автоматично відтворюватися при завантаженні відео, результат запуску на iOS і Windows можна побачити нижче.



У цій статті автор не вдається в подробиці про багаті функції, які вже є в цій першій версії, але важливо зазначити одну річ. Ви, як розробник, несете відповідальність за використання ресурсів MediaElement. Наприклад, додаток може відтворювати відео в режимі "картинка в картинці" або відтворювати аудіо у фоновому режимі, і в цих сценаріях неможливо автоматично визначити, коли потрібно очистити ресурси MediaElement.

Для цього потрібен лише один рядок коду. У фрагменті коду нижче ви можете побачити, як звільняються ресурси, коли користувач переходить зі сторінки ContentPage, на якій відображається елемент управління MediaElement.


public partial class FreeResourcesPage : ContentPage

{

    void ContentPage_Unloaded(object? sender, EventArgs e)

    {

        // Stop and cleanup MediaElement when we navigate away

        mediaElement.Handler?.DisconnectHandler();

    }


}

 

Щоб дізнатися більше про всі поточні функції MediaElement, відвідайте сторінку документації.

 

Source




Posted on 23. January 2023

Анонс .NET Community Toolkit 8.1! Покращені, швидші генератори вихідного коду MVVM, підтримка .NET 7 та багато іншого!



Анонс .NET Community Toolkit 8.1! Покращені, швидші генератори вихідного коду MVVM, підтримка .NET 7 та багато іншого!

З радістю повідомляємо про офіційний запуск версії 8.1 інструментарію .NET Community Toolkit! Ця нова версія містить нові функції, які були дуже запитувані, виправлені помилки та значні покращення продуктивності генераторів вихідного коду MVVM Toolkit, щоб покращити UX для розробників при їх використанні як ніколи!

 

Що входить до складу .NET Community Toolkit? 

Як і в інших анонсах, розпочнемо з невеликого огляду того, що входить до складу інструментарію .NET Community Toolkit. Він складається з декількох незалежних бібліотек:

Ці бібліотеки також широко використовуються у деяких програмах для роботи з поштою, які входять до складу Windows, зокрема у Microsoft Store та програмі "Фотографії"! 

Для більш детальної інформації про історію .NET Community Toolkit, ось посилання на попередній пост з анонсом 8.0.0.

 

Нижче наведено перелік основних змін, які включено до нового випуску 8.1 інструментарію .NET Community Toolkit.

Користувацькі атрибути для [ObservableProperty] (Властивість, що спостерігається) 

Як вже згадувалося у блозі з анонсом 8.1.0 Preview 1, однією з найбільш запитуваних функцій (див. #208, #217, #228) для генератора вихідного коду MVVM Toolkit була підтримка використання користувацьких атрибутів для [ObservableProperty]. Було запропоновано декілька проєктів для підтримки цієї можливості, і зрештою було вирішено використати наявну властивість: синтаксис у C#, який дозволяє розробникам позначати атрибути для поширення їх на згенеровані властивості. Це дає кілька переваг:

1. Він використовує вбудований синтаксис C#, що робить властивість "рідною" і не потребує додаткових атрибутів

2. Це розв'язує проблему анотування атрибутів, які можуть бути спрямовані лише на властивості, а не на поля

 

Тобто, у MVVM Toolkit 8.1 тепер підтримується наступний сценарій:

Це призведе до створення наступної властивості за замовчуванням:

Ви можете побачити, як згенерована властивість має два атрибути, які було вказано! Таким чином, ви можете гнучко створювати анотації для згенерованих властивостей, використовуючи вбудований синтаксис C# і без обмежень на типи атрибутів, які підтримуються цією функцією. 

Примітка: згенерований код дещо відрізняється і включає додаткові оптимізації продуктивності, не показані тут.

Ви можете знайти всі документи про нові генератори коду тут, а якщо ви віддаєте перевагу відеоверсії, Джеймс Монтемагно також зняв кілька відео про них, наприклад, це.

Аналізатори MVVM Toolkit 

Цей випуск MVVM Toolkit також є першим, в якому представлені спеціальні аналізатори, що допомагають розробникам використовувати MVVM Toolkit найкращим чином. Тобто, MVVM Toolkit більше не буде просто видавати діагностику для функцій, які використовуються неправильно (тобто таким чином, що призведе до помилки), тепер він також буде показувати рекомендації щодо покращення коду та уникнення поширених помилок! 

Перший аналізатор розглядає поширену помилку при використанні атрибута [ObservableProperty]. Розглянемо такий приклад:

Розробники неодноразово стикалися з такою проблемою, коли випадково присвоювали значення полю (а не згенерованій властивості), а потім стикалися з тим, що інтерфейс не відображав зміни, без чіткого пояснення, чому це сталося. Новий аналізатор допоможе у цих випадках, і він позначатиме всі присвоєння полів, що підтримують видиму властивість, показуючи діагностику, яка запропонує посилатися на створену властивість замість неї. Більше жодних загадкових сповіщень про відсутність властивості!

Другий новий аналізатор має на меті допомогти зменшити розмір двійкових файлів у додатках, що використовують MVVM Toolkit. Як вже згадувалося в анонсі 8.0.0, MVVM Toolkit включає декілька атрибутів (таких як [ObservableObject]), які дозволяють генераторам вставляти весь код, необхідний для реалізації інтерфейсів INotifyPropertyChanged та INotifyPropertyChanging (опціонально з додатковими допоміжними засобами) у вже наявні класи. Це особливо корисно у випадках, коли клас вже успадковується від іншого типу, ніж ObservableObject: ви можете використовувати атрибут і мати доступ до тих самих допоміжних функцій, не переробляючи логіку самостійно.

Однак це стосується лише тих випадків, коли успадкування неможливе: якщо ж це не так, краще просто успадкувати від ObservableObject і скористатися перевагами зменшеного розміру двійкового файлу, оскільки компілятору не доведеться копіювати ті самі допоміжні функції знову і знову у кожному типі. Розглянемо цей приклад:

Тут MyViewModel не успадковує від жодного типу, тому їй краще успадкувати від ObservableObject, а не використовувати атрибут [ObservableObject], щоб отримати вигоду від покращення бінарного розміру. Новий аналізатор позначатиме всі сценарії, подібні до цього, пропонуючи використовувати успадкування. Це особливо допоможе новачкам, які можуть не розуміти нюансів двох різних підходів і не знати, як зробити вибір. У таких випадках аналізатор тепер буде поруч, щоб допомогти.

Оптимізація генератора вихідних кодів MVVM Toolkit 

Як вже згадувалося, цей новий випуск також містить значні оптимізації продуктивності MVVM Toolkit, щоб ще більше покращити UX для розробників, особливо при роботі над дуже великими проєктами.

Ось лише деякі з покращень у цьому напрямку:

1. Додано багатоцільове орієнтування для Roslyn 4.3 (#428, #462): генератори вихідних кодів MVVM Toolkit тепер використовуватимуть орієнтир на Roslyn 4.3, якщо він підтримується, щоб вони могли підключатися до деяких оптимізованих API, якщо хост це підтримує. Ця функція автоматично вмикається при зверненні до MVVM Toolkit.

 

2. Використання ForAttributeWithMetadataName<T> (#436): було переключено генератори на новий високорівневий API Roslyn для зіставлення атрибутів, що значно покращує продуктивність генераторів, які спрацьовують за певними атрибутами. Наприклад, [ObservableProperty] тепер використовує цю можливість.

3. Перенесено діагностику в діагностичні аналізатори (#433, #434): було перенесено майже всю діагностику в діагностичні аналізатори, які виконуються поза процесом і незалежно від генераторів вихідних кодів. Це значно зменшує накладні витрати при наборі коду, оскільки вся логіка діагностики тепер виконується в окремому процесі й не може сповільнювати роботу IntelliSense.

4. Припинено використання символів у інкрементних провайдерах (#435): було оновлено всі інкрементні провайдери, щоб більше не поширювати символи. Це може зменшити використання пам'яті, оскільки розповсюдження символів може призвести до того, що Roslyn надмірно викорінюватиме об'єкти компіляції.

5. Більше оптимізацій продуктивності (#447, #460, #469, #487, #489): було переглянуто всі інкрементальні моделі та інкрементальні конвеєри, що значно покращило продуктивність та зменшило виділення пам'яті.

Розширення месенджерів IObservable<T> 

 

Ще однією запитуваною функцією, особливо розробниками, які інтенсивно використовують API у стилі Reactive у своїх додатках, була можливість об'єднати функціональність API месенджерів у MVVM Toolkit. Тепер це підтримується завдяки новим розширенням IObservable<T> для інтерфейсу IMessenger. Їх можна використовувати наступним чином:

 

... Ось і все! Це розширення створить об'єкт IObservable<T>, який можна використовувати для підписки на повідомлення і динамічної реакції на них. Також підтримується вказівка різних токенів за допомогою окремих перевантажень. Ось ще один приклад, що демонструє наскрізне використання нового API:

Підтримка .NET 7 та C# 11 

Цей новий випуск .NET Community Toolkit також додає .NET 7 TFM до пакета HighPerformance і містить кілька змін, що дозволяють скористатися новими можливостями мови C# 11, зокрема, посиланнями на поля (ref fields).

Наступні типи більше не знаходяться у попередньому перегляді й були оновлені для використання нових правил безпеки ref-полів:

Приклад, де вони можуть бути використані, наведено нижче:

Тобто, тип NullableRef<T> фактично дозволяє методу мати параметр out ref T, який не може бути виражений в C# іншим чином. Планується також розширити поверхню API цих типів у майбутньому, щоб ці типи могли стати простою у використанні альтернативою GC-ref арифметиці з використанням типу Unsafe, яка також може бути візуально більш схожою на традиційну арифметику з вказівниками.

 

Крім того, всі типи ref-структур, яких ще не було у попередньому перегляді, було оновлено для внутрішнього використання полів ref для покращення продуктивності. До них відносяться:

Інші зміни 

У цьому новому випуску набагато більше змін!

Ви можете переглянути повний список змін на сторінці релізу на GitHub.

Розпочинайте прямо зараз! 

Ви можете знайти весь вихідний код у репозиторії GitHub, деякі рукописні документи на MS learn та повні посилання на API на вебсайті браузера .NET API. Якщо ви хочете зробити свій внесок, не соромтеся повідомляти про проблеми або ділитися з нами своїм досвідом! Щоб стежити за обговоренням у Twitter, використовуйте хештег #CommunityToolkit. Всі ваші відгуки дуже допомагають формувати напрямок розвитку цих бібліотек, тому обов'язково діліться ними!

Більше ресурсів 

Якщо ви хочете дізнатися більше про MVVM Toolkit, ви також можете переглянути це відео з нещодавньої конференції .NET Conf 2022, де показано, як можна використовувати MVVM Toolkit, новий генератор коду та всі нові функції в 8.1:

Існує ціла екосистема доступних Toolkit'ів з безліччю корисних API для створення .NET-додатків! Дізнайтеся більше про них у документації MS learn!

 

Вдалого кодування!

Source



Posted on 9. November 2022

Анонс .NET Community Toolkit v8.1.0 Preview 1

Анонс .NET Community Toolkit v8.1.0 Preview 1

 

Пропонуємо вашій увазі попередню версію 1 майбутнього релізу .NET Community Toolkit 8.1! Ця перша офіційна попередня версія містить кілька дуже запитуваних нових функцій, виправлення помилок і, найголовніше, значне покращення продуктивності генераторів вихідних кодів MVVM Toolkit, завдяки чому користувацький інтерфейс розробника при їх використанні навіть у дуже великих проєктах стане кращим, ніж будь-коли!

Що входить до інструментарію .NET Community Toolkit? 

 

Щоб дати короткий огляд того, що мстить інструментарій .NET Community Toolkit, наведемо перелік бібліотек, з яких він складається:

Бібліотеки також широко використовуються у деяких програмах вхідних повідомлень, що постачаються з Windows, таких як Microsoft Store! 🚀

Для більш детальної інформації про історію розвитку інструментарію .NET Community Toolkit, ознайомтеся з посиланням на попередній пост з анонсом версії 8.0.0.

Ось перелік основних змін, які ви можете очікувати в цьому новому випуску.

Користувацькі атрибути для [ObservableProperty

Однією з найбільш запитуваних функцій (див. #208, #217, #228) для генератора вихідного коду MVVM Toolkit була підтримка використання користувацьких атрибутів для [ObservableProperty]. Було запропоновано декілька проєктів для підтримки цього, і врешті-решт було вирішено використати наявну властивість: синтаксис у C#, який дозволяє розробникам позначати атрибути для розповсюдження на згенеровані властивості. Це дає нам декілька переваг:

 

  • Він використовує вбудований синтаксис C#, що робить функцію "рідною" і не потребує додаткових атрибутів
  • Це розв'язувати проблему анотування атрибутів, які можуть бути спрямовані лише на властивості, а не на поля
Тобто, у MVVM Toolkit 8.1 тепер підтримується наступний сценарій:
Після цього буде згенеровано наступну властивість за лаштунками:

 

Ви можете побачити, як згенерована властивість має два атрибути, які було вказано! Це забезпечує повну гнучкість в анотаціях для згенерованих властивостей, використовуючи вбудований синтаксис C# і без обмежень на типи атрибутів, які підтримуються цією функцією. 🙌

Примітка: згенерований код дещо відрізняється і містить додаткові оптимізації продуктивності, які тут не показано.

Ви можете знайти всі документи про нові генератори вихідних текстів тут, а якщо ви віддаєте перевагу відеоверсії, Джеймс Монтемагно також зробив кілька відео про них, наприклад, це.

Оптимізація генератора вихідних текстів MVVM Toolkit 

Як вже було сказано, ця нова попередня версія також містить значну оптимізацію продуктивності MVVM Toolkit, щоб ще більше покращити UX для розробників, особливо при роботі над дуже великими рішеннями. Команда провела багато часу, покращуючи архітектуру всіх генераторів і спілкуючись з інженерами з команди Roslyn, щоб переконатися, що виконується все можливе, щоб отримати від них максимальну продуктивність.

Ось лише деякі з удосконалень в цьому напрямку:

 

  • Додано багатоцільове націлювання для Roslyn 4.3 (#428, #462): генератори вихідних текстів MVVM Toolkit тепер використовуватимуть ціль Roslyn 4.3, якщо воно підтримується, щоб вони могли підключитися до деяких оптимізованих API, якщо хост це підтримує. Це автоматично вмикається при посиланні на MVVM Toolkit.
  • Використано ForAttributeWithMetadataName<T> (#436): було переключено генератори на новий високорівневий API Roslyn для зіставлення атрибутів, що значно покращує продуктивність генераторів, які спрацьовують за певними атрибутами. Наприклад, [ObservableProperty] тепер використовує це.
  • Перенесено діагностику в діагностичні аналізатори (#433, #434): перенесено майже всю діагностику в діагностичні аналізатори, які виконуються поза процесом і незалежно від генераторів джерел. Це значно зменшує накладні витрати при наборі тексту, оскільки вся логіка діагностики тепер виконується в окремому процесі й не може сповільнювати роботу IntelliSense.
  • Припинено використання символів у інкрементних провайдерах (#435): оновлено всі інкрементні провайдери, щоб більше не поширювати символи. Це може зменшити використання пам'яті, оскільки розповсюдження символів може призвести до того, що Roslyn надмірно викорінюватиме об'єкти компіляції.
  • Більше оптимізацій продуктивності (#447, #460, #469, #487, #489): переглянуто всі наші інкрементні моделі та інкрементні конвеєри, щоб значно покращити продуктивність та зменшити виділення пам'яті.

 

Розширення месенджерів IObservable<T> 

 

Ще однією функцією, яку просили розробники, особливо ті, що активно використовують API у стилі Reactive у своїх додатках, була можливість об'єднати функціональність API месенджерів у MVVM Toolkit. Тепер це підтримується завдяки новим розширенням IObservable<T> для інтерфейсу IMessenger. Ви можете використовувати їх наступним чином:
...І це все! Це розширення створить об'єкт IObservable<T>, який можна використовувати для підписки на повідомлення і динамічної реакції на них. Також підтримується вказівка різних токенів за допомогою окремих перевантажень. Ось ще один приклад, що демонструє наскрізне використання нового API:

Підтримка .NET 7 та C# 11 

Цей новий попередній випуск .NET Community Toolkit також додає .NET 7 TFM до пакета HighPerformance і містить кілька змін, що дозволяють скористатися новими можливостями мови C# 11, зокрема, полями посилань.

Наступні типи більше не знаходяться в режимі попереднього перегляду, вони були оновлені відповідно до нових правил безпеки арбітрів:
Приклад того, де вони можуть бути використані, наведений нижче:
Тобто, тип NullableRef<T> фактично дозволяє методу мати параметр out ref T, який не може бути виражений в C# іншим чином. Також планується розширити поверхню API цих типів у майбутньому, щоб ці типи могли надавати просту у використанні альтернативу GC-реф-арифметиці з використанням типу Unsafe, яка також може бути візуально більш схожою на традиційну арифметику з вказівниками.

Інші зміни 

У цьому новому випуску набагато більше!

Ви можете переглянути повний список змін на сторінці релізу на GitHub.

Почніть вже сьогодні! 

Ви можете знайти весь вихідний код у репозиторії GitHub, деякі рукописні документи на MS learn та повні посилання на API на вебсайт браузера .NET API. Щоб стежити за обговоренням у Twitter, використовуйте хештег #CommunityToolkit. Всі ваші відгуки дуже допомагають формувати напрямок розвитку цих бібліотек, тому обов'язково діліться ними!

Більше ресурсів 

Якщо ви хочете дізнатися більше про MVVM Toolkit, ви також можете переглянути це відео з останньої конференції .NET Conf Focus on MAUI, яка відбулася раніше в цьому році, де показано, як можна використовувати MVVM Toolkit і всі нові функції генератора вихідних кодів для створення MAUI-додатків:

Існує ціла екосистема доступних наборів інструментів з безліччю корисних API для створення .NET-додатків! Налаштуйтеся на майбутню конференцію .NET Conf 2022, щоб дізнатися більше!

Вдалого кодування!