Меня зовут Артем Абрамович и я являюсь фрилансером-вордпресером. Занимаюсь настройкой и редактированием сайтов созданных на CMS WordPress. Это основная моя специализация, есть еще несколько работ, которыми я занимаюсь, но обо этом вы можете более подробно узнать из моего портфолио.
7 комментариев к “Транзиенты (Временные опции). Что это и как пользоваться”
Хорошее обзорное видео. Для понимая, зачем нужны временные опции — вполне. Стоит добавить, что временные опции активно используются плагинами объектного кеширования. Также, если не указать время жизни опции, то она получится обычной опцией (только со своеобразным префиксом), причем автозагружаемой, что может оказаться негативным, если опция не нужна на всех страницах сайта.
Ещё получение временной опции более долгий процесс (но совсем не на много), так как надо получить два поля из базы — значение поля и её время жизни + другие обработки для установления жизнеспособности опции. Потому их применение должны быть оправдано. О целесообразности в видео сказано. Спасибо!
Программируем «TurboSky T8» ( Baofeng BF480)
Финты WordPress
Тебе спасибо! Шикарный комментарий!
Все верно, на получение уходит 2 запроса, потому и используют не везде
Артем подскажи пожалуйста, а ты тему Jupiter, которая засветилась в видео)), покупал или скачал откуда-либо ?
Источник: wordpressify.ru
TIDRADIO — bluetooth программатор раций Baofeng
Пост обновляю. Разбираясь постепенно с прибором и внося корректировки.
Нашел на просторах китайского интернета.
Отзывов и описаний, тем более на русском, не нашел. Поэтому решил рассказать.
И так.
Блютуз программатор фирмы Tidradio с заточкой под рации baofeng.
Работает через смартфон.
Прислан был в такой вот упаковке.
Имеет встроенный аккумулятор и гнездо usb Type-C.
Кнопка вкл выкл.
И светодиод состояния.
Подключается как и обычный кабель в два гнезда гарнитуры.
Дальность блютуза минимальна. Сантиметров 10 от смарта и закачка уже еле еле идет. Еще немного отдалить и загрузка выгрузка вообще с ошибкой прерываются, хотя прибор на связи по блютузу.
Все предельно просто.
На этом описание железа окончено. Больше добавить нечего.
Далее про программу.
Зовется Odmaster.
Скачивается с плеймаркета. Бесплатная. Регистрация простая. Интерфейс английский.
Напичкана какими-то чатами с инструкциями, каналами общения, друзьями и т.д. Т.е. всем тем что мне не особо нужно. Зачем мне друг с канады?
Программирование раций через программу CHIRP
Но есть там и полезный раздел, куда люди скидывают свои сохраненные конфиги, поименовав их. Возможно путешественники смогут найти что-то полезное. Хотя к поездкам готовятся заранее а не в полях уже.
Про само программирование.
Интерфейс понятен.
подключаемся по блютуз как к любым наушникам и прочему. И видим название адаптера вверху окна
Далее выбираем модель рации. Поддерживает внушительный список моделей. Но судя по названиям моделей, это все какие-то клоны баофенгов.
Кенвудов и других совместимых по штекеру нет в списке.
Т.е. заточка идет под баофенг.
И переходим к настройкам.
В списке предустановок для пакетной заливки есть каналы gmrs, murs. pmr и lpd нет. В данном списке будут отображаться ваши сохраненные настройки, если вы их выгрузите из рации и сохраните.
так же подразумевается список репитеров. Но или я не разобрался или не в той стране живу. В общем список пуст.
Смог в свою легко и просто вписать параметры репитера с именем в один из каналов.
Так же есть общие настройки рации.
! При заливке настроек в рацию, даже если изменили всего один канал, заливаются все каналы и общие настройки дефолтные из программы.
Поэтому лучше сначала считать со своей. Потом исправить добавить и залить, перепроверив общие настройки на второй вкладке. Иначе пытаясь записать всего один новый канал, вы удалите все сохраненные в рации каналы и настройки.
Можно считать и сохранить с рации свои настройки. после чего экспортировать в аналогичные радейки. а может и другие модели. сохраненные настройки будут храниться в том самом выше показанном на скрине списке, где видны gmrs murs настройки.
Можно с браузера на ПК зайти под своим логином на tidradio и там их в окне браузера отредактировать. После чего они автоматом обновятся и в смартфоне, откуда уже и по рациям можно раскидать.
И теперь самое главное о программе.
ОНА полноценно НЕ РАБОтАЕТ БЕЗ ИНТЕРНЕТА!
При переводе телефона в авиарежим, программа отказывается заходить в настройки рации, хотя по блютузу в этот момент коннект имеется.
Вердикт. железяка в целом работоспособная. один досадный ньюанс — невозможность редактирования без интернета.
Источник: www.drive2.ru
Облегченная разработка WP7 приложений при помощи Caliburn.Micro framework (ч.1)
Как можно догадаться из названия, эта статья будет просвещенна framework’у Caliburn.Micro. Я постараюсь показать, что полезного может дать использование этого framework’а разработчику под платформу WP7, какие задачи он решает, его достоинства и недостатки.
Но самый важный вопрос, на который я буду пытаться ответить в течении всей статьи, это зачем вообще нужен еще один промежуточный слой, в виде какого-то framework’а, в достаточно устоявшемся царстве WP7.
Если вам интересна эта тема, то добро пожаловать под кат.
Подготовка
Я предполагаю, что материалы этой статьи будут интересны в основном людям уже знакомым с разработкой под WP7. Поэтому я не буду рассказывать как создать проект в VS и т.п., а буду полагать, что вы это уже знаете или можете узнать из множества других открытых источников.
- VS 2010 SP1
- Windows Phone SDK 7.1
- Caliburn.Micro
MVVM или Глава вместо предисловия
Приложение WP7 состоит из наборы экранов/страниц (Windows Phone Page), эти экраны представляют какие-то данные, например, записи в DB. Возникает вопрос, как связать эти данные и элементы UI на экране.
// PageTitle — TextBlock PageTitle.Text = GroupConnector(GroupId).Name; // Users — ListBox Users.ItemsSource = GroupConnector(GroupId).Users;
- Сложно проектировать и поддерживать. Код и UI-элементы находятся в тесной связи, а это затрудняет процесс разработки т.к. требует дополнительные ресурсы для синхронизации UI и обслуживающего его кода. Так же такой код тяжело воспринимается сторонними людьми, в особенности если он содержит много элементов, а не два, как в нашем примере.
- Плохо распараллеливается. Т.е. программист зная с какими данными он работает, не может проверить работоспособность своего кода без готовой реализации UI. Если созданием UI и функциональным кодом занимаются разные люди, то эта проблема усиливается еще больше.
- Сложно писать unit-тесты. Код завязанный на элементы UI плохо поддается unit-тестированию, т.к. требует наличия xaml’а и всей инфраструктуры вокруг, что не быстро, проблематично если unit-тесты находятся в другом проекте или UI еще не готов (привет адептам TDD).
Если говорить коротко, то смысл MVVM-подхода в разнесении View от ее представления. Т.е. в хорошо спроектированной системе, независимо от того как будет выглядеть ваш конечный UI, представление останется неизменным, т.к. отражает высокоуровневое представление о данных, не прявязанное к конкретной реализации.
При разработке WP7-приложений MVVM-подход применяется повсеместно. Некоторые делают собственные решения, другие использует уже готовые наработки в виде одного из framework’ов (например, Prism и MVVM Light Toolkit). Caliburn.Micro как раз и является таким framework’ом. Т.е. это реализация MVVM-подхода с набором приятных плюшек.
Начало работы
- Создадим папку CaliburnMicro (или с любым другим названием) внутри проекта и скопируем туда файлы Caliburn.Micro.dll, Caliburn.Micro.Extensions.dll и System.Windows.Interactivity.dll из дистрибутива CM (binWP71Release).
- Добавим новые файлы в reference’ы.
Создадим класс SampleBootstrapper, наследник PhoneBootstrapper и добавим его в наш проект:
public class SampleBootstrapper : PhoneBootstrapper < private PhoneContainer _container; protected override void Configure() < _container = new PhoneContainer(RootFrame); _container.RegisterPhoneServices(); AddCustomConventions(); >private static void AddCustomConventions()<> protected override object GetInstance(Type service, string key) < return _container.GetInstance(service, key); >protected override IEnumerable GetAllInstances(Type service) < return _container.GetAllInstances(service); >protected override void BuildUp(object instance) < _container.BuildUp(instance); >>
Пусть вас не смущает этот класс, в дальнейшем из него нам понадобится только метод Configure.
Теперь нужно указать приложению, что нужно использовать SampleBootstrapper. Для этого нужно отредактировать файл App.xaml, удалив оттуда все кроме ссылки на наш Bootstrapper:
Т.к. обработку евентов вроде Launching, Activated и пр. теперь на себя берет SampleBootstrapper, то старые методы, отвечающие за это раньше, из App.xaml.cs можно удалить. Т.е. класс App, теперь будет выглядеть намного проще:
public partial class App < public App() < InitializeComponent(); >>
Компилируем и запускаем, если все выглядит как раньше, т.е. до изменений связанных с CM, значит вы все сделали правильно и можно идти дальше, если же приложение падает, то значит была допущена ошибка и нужно ее исправить до продолжения следующих экспериментов.
Первая ViewModel
Без использования сторонних framework’ов и при использовании ViewModel, эта ViewModel создается следующим образом. Создается класс реализующий ViewModel, далее ссылка на него передается в DataContext внутри страницы PhoneApplicationPage аля:
DataContext = ViewModelsConstructor.GetViewModel(this);
Тоже самое можно сделать и средствами xaml. Все это нужно чтобы работал binding пропертей ViewModel и элементов View (UI контролов).
В CM этот подход немного отличается. В нем нет необходимости устанавливать контекст самостоятельно, это на себя берет framework. Также нет необходимости работать с DataContext и файлами *.xaml.cs вообще, что позволяет еще больше приблизиться к идеальному MVVM, еще дальше отстранившись от View и xaml в частности. В CM применяется декларативный подход для описания VM (ViewModel), который я далее и постараюсь продемонстрировать.
После создания приложения у вас уже есть экран, создаваемый по умолчанию: MainPage. Давайте попробуем создать для него класс реализующий ViewModel с помощью CM. Для этого нужно создать класс с таким же именем как имя файла с расширением xaml, с окончанием ViewModel (т.е. класс MainPageViewModel), поместить его в отдельный файл с таким же именем и отнаследовать от CM класса Screen (в этом классе уже инкапсулированы все методы для работы с текущей страницей, но об этом я напишу позже). Т.е. класс должен выглядеть вот так:
public class MainPageViewModel : Screen < public MainPageViewModel() < >>
Последнее, что осталось сделать это зарегистрировать нашу VM в Bootstrapper’e. Для этого в классе SampleBootstrapper, в метод Configure достаточно добавить следующий код:
_container.PerRequest();
И все! Наша ViewModel создана и будет привязана CM к странице MainPage при ее создании. PerRequest означает что класс MainPageViewModel будет создаваться каждый раз при запросе страницы MainPage. Если использовать метод Singleton, то класс MainPageViewModel будет реюзиться при всех последующих запросах.
Давайте посмотрим как работает binding свойств. Для этого добавим в наш VM класс свойство PageTitle и присвоим ему какое-нибудь значение, например, «sample page»:
public class MainPageViewModel : Screen < public string PageTitle < get; set; >public MainPageViewModel() < PageTitle = «sample app»; >>
И запустим приложение. Название страницы изменилось! Это произошло потому что CM взял все вопросы по связи ViewModel и View на себя и связал свойство PageTitle по его имени (в xaml оно называется также).
Привычный binding через указания связи напрямую (аля Text=»» ) в xaml, также работает, но согласитесь, без него значительно проще.
Это был достаточно простой пример, о более сложных вариантах binding’а и возможностях CM в этом плане я расскажу позже, а пока продолжим.
Навигация
Помните наш пример с пользователями и группой из AD? Логично предположить, что для того чтобы показать информацию о какой-то группе нужно куда-то передать информацию о том, а что это за группа. Для простоты пусть это будет ее имя. Это «куда-то» конечно же VM, т.к. именно ей необходимо знать, что это за группа, чтобы вернуть нужные данные в View.
Стандартный способ решения такой задачи, это навигация с параметрами. Т.е. мы говорим, что хотим перейти на такой-то экран (в данном случае со списком пользователей), а в качестве параметра передаем идентификатор группы. Обычно это делается вот так:
NavigationService.Navigate(new Uri(«/GroupPage.xaml?name=Administrators», UriKind.Relative));
А далее в OnNavigatedTo страницы GroupPage.xaml этот параметр извлекается конструкцией:
var name = NavigationContext.QueryString[«name»];
Потом передается (например, через конструктор) в класс реализующий модель, а далее она передается в DataContext.
Согласитесь, не самое красивое решение, для такой простой задачи.
Другой популярный способ это использовать PhoneApplicationService.Current.State, для обмена шаренными данными:
PhoneApplicationService.Current.State[«name»] = «Administrators»;
Или просто через глобальные переменные внутри класса Application, благо его экземпляр можно получить где угодно через Application.Current.
Вообщем все это достаточно криво. Последние два примера плохи тем что нелепо использовать шаренные данные для обмена между экранами, в особенности когда есть стандартный способ для этого. Первый пример плох тем что очень легко сделать опечатку в пути, да и «шелуха» с выдергиванием этого значения (еще хуже если их много) из NavigationContext, с последующей передачей все этого куда-то, тоже не радует.
А вот как это делается в CM:
_navigationService.UriFor() .WithParam(x => x.Name, «Administrators») .Navigate();
GroupPageViewModel — VM, сделанная по аналогии как мы делали MainPageViewModel, с публичным свойством Name:
public class GroupPageViewModel : Screen < public string Name < get; set; >>
А _navigationService — объект реализующий INavigationService, которой можно получить внутри любой VM унаследованной от класса Screen и использовать для навигации между экранами. Через метод WithParam можно задать свойства VM у страницы назначения. INavigationService — это обертка над стандартным NavigationService, включающая в себя весь его функционал и расширяющая дополнительными возможнотсями.
Вот так выглядит получение экземпляра INavigationService для класса MainPageViewModel, CM просто передает объект INavigationService в конструктор MainPageViewModel:
public class MainPageViewModel : Screen < private INavigationService _navigationService; public string PageTitle < get; set; >public MainPageViewModel(INavigationService navigationService) < PageTitle = «sample app»; _navigationService = navigationService; >>
- Очень мало кода, который нужно написать разработчику, чтобы передать параметр в VM.
- Т.к. INavigationService специализирован классом VM назначения и параметры задаются в привязке к этому классу, то невозможно ошибиться/опечататься при задании этих параметров, т.к. такой код просто не скомпилируется.
- Т.к. передается интерфейс, то поведение INavigationService хорошо мокируется, что очень удобно при написании unit-test’ов.
- Код полностью отвязан от UI.
- Сложные типы так передать не получится. Здесь нет никакой магии, CM не может сделать, то чего нет в WP7, т.к. базируется на ее же возможностях. Реализация базируется на стандартной реализации NavigationService (та что в первом примере). Но это можно обойти если использовать сериализацию и немного подправить исходники CM.
INotifyPropertyChanged
Оставим пользователей из AD, и представим другой пример. Допустим у нас есть почтовая программа, на одной из страниц которой находится список доступных почтовых ящиков с бейджиком непрочитанных сообщений.
Основное отличие от предыдущих примеров заключается в том, что данные теперь не статичные, а могут изменяться во времени (счетчик непрочитанных сообщений). Т.е. если представить, что у нас есть свойство отвечающее за количество непрочитанных сообщений, то нужен механизм чтобы уведомлять View о том, что оно изменилось. Для этой цели используется механизм уведомлений на базе реализации интерфейса INotifyPropertyChanged. Стандартный способ реализация этого подхода выглядел бы так:
public class MailboxPageViewModel : INotifyPropertyChanged < private int _unreadCount; public int UnreadCount < get < return _unreadCount; >set < _unreadCount = value; NotifyPropertyChanged(«UnreadCount»); >> public event PropertyChangedEventHandler PropertyChanged; public void NotifyPropertyChanged(string propertyName) < if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); >>
Как видно, здесь сигналится event PropertyChanged при изменении свойства UnreadCount, что приведет к перечитыванию View его значения.
- Имя свойства задается по имени, а это чревато ошибками.
- При обновлении свойства не из UI-потока, приложение упадет с Invalid cross-thread access исключением.
public class MailboxPageViewModel : Screen < private int _unreadCount; public int UnreadCount < get < return _unreadCount; >set < _unreadCount = value; NotifyOfPropertyChange(() =>UnreadCount); > > >
CM метод NotifyOfPropertyChange решает описанные проблемы и доступен сразу же «из коробки».
В CM также можно найти класс BindableCollection, решающий схожие проблемы с доступом из не UI-потоков другого класса, реализующего INotifyPropertyChanged и используемого для хранения коллекций объектов, класса ObservableCollection. Т.е. при использовании BindableCollection можно не беспокоится о том в каком потоке вызываются методы коллекции.
Tombstone
Одна из проблем, с которой сталкиваются разработчики при написании приложений для WP7, является необходимость восстановления состояния приложения после выхода из состояния Tombstone.
В WP7 для этого используется PhoneApplicationService.State, IsolatedStorage и прочие решения. Работать с тем что есть без дополнительных оберток не так уж удобно. CM предлагает элегантное решение. Если вам нужно чтобы данные VM пережили tombstone, то достаточно создать класс c именем VM и окончанием Storage. Класс для нашего примера со списком пользователей будет называться GroupPageViewModelStorage и будет выглядеть вот так:
public class GroupPageViewModelStorage : StorageHandler < public override void Configure() < Property(x =>x.Name) .InPhoneState() .RestoreAfterActivation(); > >
StorageHandler — это класс CM, реализующий стратегия сохранения данных внутри VM. В этом примере, мы говорим что хотим сохранить свойство Name внутри PhoneApplicationService.State и то что данные нужно восстановить вместе с активацией страницы.
Т.к. CM ничего не знает и не может знать о данных хранимых в Model, то их нужно сохранять отдельно. Для этого нужно добавить необходимый код по сериализации/десериализации, отвечающий логике вашего приложения, внутрь соответствующих методов Bootstapper’а (Launching, Closing, Deactivated и т.п.).
Конец первой части
Здесь я понял, что статья получается больше чем я ожидал вначале и что необходимо написать еще столько же. Это более чем достаточно для вводно-обзорной статьи, поэтому я решил разбить ее на две части.
Продолжение следует.
- caliburn.micro
- windows phone 7
- разработка
- мобильная разработка
Источник: habr.com