Статьи

Портирование приложения Windows Phone 8.0 на Caliburn Micro 2.0

В своей повседневной работе в Funambol я работаю над приложением OneMediaHub , которое является клиентом Windows Phone для облачных сервисов, предлагаемых компанией. Приложение построено с использованием шаблона MVVM и Caliburn Micro в качестве основы. Теперь, когда цикл разработки новой версии клиента завершен, одной из моих целей перед началом работы над новыми функциями для следующей версии является обновление Caliburn Micro с предыдущей версии (1.5.3) до самой последней ( 2.0).

Однако, как я сам обнаружил, процедура не так проста: Caliburn Micro является большим улучшением по сравнению с предыдущей версией, но она также включает в себя множество критических изменений. В этом посте я подробно опишу наиболее важные, с которыми мне пришлось столкнуться во время миграции.

Изменения в загрузчике

Boostrapper — это базовый класс, который заменяет один из приложений и выполняет инициализацию приложения среди всех служб и соглашений Caliburn.

Есть два важных изменения в усилителе с Caliburn Micro 2.0:

  • В предыдущем выпуске класс загрузчика должен был наследоваться от класса PhoneBootstrapper . Теперь вместо этого базовый класс был переименован в PhoneBootstrapperBase .
  • Теперь в конструкторе класса загрузчика вам нужно вызвать метод Initialize () , тогда как в предыдущей версии это не требовалось.

Вот полная рабочая инициализация загрузчика для Caliburn Micro 2.0:

public class CaliburnBootStrapper : PhoneBootstrapperBase
{
    public OneMediaHubBootStrapper()
    {
        this.Initialize();
    }
}

Благодаря Маттео Тумиату, который указал мне правильное направление: без вызова метода Initialize () приложение застряло в фазе загрузки, без каких-либо предупреждений или исключений.

Изменения в EventAggregator

EventAggregator — это класс, используемый для управления сообщениями (которые, в конце концов, являются простыми объектами), которые можно отправлять и получать из разных классов (например, двух ViewModel или ViewModel и View). Этот подход помогает создать канал связи между различными классами, сохраняя при этом фундаментальную концепцию MVVM «разделения интересов». Фактически, когда класс отправляет сообщение, он не знает, кто его получит: это класс получателя, который просто зарегистрирует себя для обработки сообщений определенного типа.

Для того, чтобы отправить сообщение в Caliburn Micro 1.5 мы использовали публикации () метод IEventAggregator класса, который просто отправил объект с помощью потока пользовательского интерфейса. В Caliburn Micro 2.0 этот метод больше не существует, и его заменили несколькими методами, которые поддерживают большее количество сценариев, таких как отправка сообщений в фоновом потоке или использование потока пользовательского интерфейса, но асинхронно.

Если вы хотите заменить метод Publish () без изменения старого поведения (чтобы сообщение отправлялось синхронно в потоке пользовательского интерфейса), вам просто нужно использовать новый метод PublishOnUIThread () .

В противном случае, если вы хотите улучшить производительность и избежать перегрузки потока пользовательского интерфейса, вы можете использовать новую асинхронную версию, а именно PublishOnUIThreadAsync () : однако для этого вам потребуется немного больше работы для завершения переноса; Поскольку метод является асинхронным, вам необходимо добавить в качестве префикса ключевое слово await и пометить метод контейнера асинхронным . Но, прежде всего, вам нужно убедиться, что вы правильно управляете асинхронным шаблоном: например, если ваш метод, отправляющий сообщение, помечен как void и не является обработчиком событий, вы должны изменить его так, чтобы он возвращает задание, чтобы вызывающий мог правильно его ожидать.

private async Task SendMessage()
{
   
    await eventAggregator.PublishOnUIThreadAsync(new SimpleMessage());
   
}

Есть также еще один полезный новый метод, предлагаемый классом IEventAggregator , который называется PublishOnBackgroundThread () : при его использовании метод Handle () , который его получит, будет выполняться в фоновом потоке, а не в потоке пользовательского интерфейса. Это полезно, когда класс получателя должен выполнить много задач, потребляющих ЦП, когда сообщение получено.

Новое пространство имен для класса Message

В моем приложении я обнаружил себя несколько раз, используя присоединенное свойство Message.Attach , которым можно управлять в событиях ViewModel, которые вызываются элементами управления в пользовательском интерфейсе. В предыдущей версии Caliburn Micro класс Message был определен внутри Caliburn.Micro в сборе. Это означает, что для его использования вы добавили следующее пространство имен в определение XAML:

xmlns:micro="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro

Теперь сборка, содержащая класс Message, изменяется на Caliburn.Micro.Platform : как следствие, вам придется изменить все ваши определения пространств имен XAML на

xmlns:micro="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro.Platform"

Управление панелью приложения

Для управления панелью приложения Caliburn я использовал в своем проекте сторонний компонент, разработанный Kamran Ayub, который называется CaliburnBindableAppBar. Я подробно рассказал об этом в следующем посте . Проблема возникает, если, как и я, вы установили компонент с использованием NuGet: фактически, доступная версия скомпилирована с Caliburn Micro 1.5 и не будет работать, если вы обновите свой проект до Caliburn Micro 2.0. Однако разработчик уже обновил проект: на GitHubВы можете видеть, что компонент уже поддерживает Caliburn Micro 2.0, как указано в журнале изменений. Я уже связался с разработчиком, и он пообещал мне, что скоро собирается обновить пакет на NuGet; однако, если вам нужно использовать обновленную панель приложений прямо сейчас, решение простое: просто скачайте проект с GitHub и скомпилируйте его самостоятельно или добавьте в свое решение.

Это все!

Если у вас был подобный опыт, и вы нашли другие изменения, которые следует упомянуть, не стесняйтесь оставлять комментарии!