Wśród wymagań certyfikacyjnych można znaleźć kilka dotyczących wydajności uruchamiającej się aplikacji. Dwa najważniejsze to:
[list icon=”check”]
- aplikacja powinna wyświetlić pierwszy ekran w czasie nie dłuższym niż 5 sekund. Ekranem tym może być splash screen,
- nie później niż 20 sekund po uruchomieniu, aplikacja powinna reagować na działania użytkownika.
[/list]
Można się zastanawiać, czy to jest dużo. Moim zdaniem bardzo trudno jest przekroczyć te dwa ograniczenia. Z drugiej jednak strony, patrząc na aplikację z punktu widzenia użytkownika, czekanie 20 sekund na uruchomienie się aplikacji jest strasznie irytujące. Należy pamiętać, że po kolejnych 10 sekundach może uruchomić się wygaszacz ekranu na telefonie. Z tego powodu proponuję zastanowić się nad możliwościami przyśpieszenia startu aplikacji.
Zakładam, że takie rzeczy jak:
[list icon=”check”]
- uruchamianie długich operacji w innym wątku niż wątek UI,
- powiadamianie użytkownika o statusie operacji trwających dłużej
[/list]
są oczywiste i nie wymagają wytłumaczenia.
Przejdę, więc od razu do sedna. Analizując programy na platformę Windows Phone można spotkać się bardzo często z dwoma podejściami, gdzie należy umieścić kod, który powinien wykonać się zawsze przed uruchomieniem programu.
W obsłudze zdarzenia Launching aplikacji – w tym przypadku należy pamiętać o ograniczeniu 10 sekund na jego wykonanie się.
// Code to execute when the application is launching (eg, from Start) // This code will not execute when the application is reactivated private void Application_Launching(object sender, LaunchingEventArgs e) { // Do something }
W konstruktorze głównej strony:
public partial class MainPage : PhoneApplicationPage { // Constructor public MainPage() { InitializeComponent(); // Do something }
Oba pomysły nie są do końca poprawne. Największą ich wadą jest to, że kod w nich zawarty wykona się przed wyświetleniem pierwszej strony i opóźni jej pojawienie się. Dla użytkownika naszej aplikacji oznaczać to będzie dłuższe czekanie na pojawienie się jakiejkolwiek informacji na ekranie telefonu. Dodatkowo takie zachowanie może doprowadzić do odrzucenia naszej aplikacji w procesie certyfikacyjnym w sytuacji, gdy nie zostaną spełnione wcześniej wspomniane wymogi.
W celu uniknięcia tej sytuacji i zwiększenia komfortu pracy z aplikacją proponuję opóźnić wykonanie tego kodu do momentu, aż pierwsza strona załaduje się poprawnie. Uzyskanie tego efektu jest bardzo proste. Wystarczy tylko podpiąć się pod zdarzenie Loaded na głównej stronie:
public partial class MainPage : PhoneApplicationPage { // Constructor public MainPage() { InitializeComponent(); this.Loaded += new RoutedEventHandler(MainPage_Loaded); } private void MainPage_Loaded(object sender, RoutedEventArgs e) { // Do something }
Po takiej zmianie pierwszy ekran programu powinien pojawić się znacznie szybciej. Jeśli jednak, cały czas jeszcze istnieje potrzeba dalszego opóźnienia wykonywania tych czynności to można do zaproponowanego rozwiązania dodać timer:
public partial class MainPage : PhoneApplicationPage { private DispatcherTimer timer; // Constructor public MainPage() { InitializeComponent(); this.timer = new DispatcherTimer(); this.timer.Interval = TimeSpan.FromSeconds(1); this.timer.Tick += new EventHandler(timer_Tick); this.Loaded += new RoutedEventHandler(MainPage_Loaded); } private void MainPage_Loaded(object sender, RoutedEventArgs e) { this.timer.Start(); } private void timer_Tick(object sender, EventArgs e) { this.timer.Stop(); // Do something }
Stosując takie rozwiązanie można opóźnić wykonanie kodu o dowolny czas.
W sumie to wszystko zależy od sytuacji, która wymaga optymalizacji. Czasem pomaga wrzucenie do Loaded, innym razem warto zastanowić się nad dynamiczną zmianą bindowania z kodu.
Opcją też jest podział ma mniejsze biblioteki.
Niejednokrotnie uproszczenie architektury, też można znacznie przyspieszyć działanie programu. Szczególnie jeśli zoptymalizujemy ilość warstw w programie.
Jakimś rozwiązaniem może też być opóźniona inicjalizacja wszystkiego co się da. Może to jednak wywołać „mulenie” się aplikacji w trakcie użytkowania.
Co do pomysłu z Loaded to trzeba pamiętać że na tym zdarzeniu trochę się dzieje np. następuje uruchomienie DataBingów a to znowu może generować pewien ruch we ViewModelu
Warto się jeszcze zainteresować podzieleniem aplikacji troszeczkę jeżeli aplikacja już jest tak skomplikowana że jest w stanie się uruchamiać ponad 20s (osobiście wolał bym nawet 5s nie przekraczać na ładowanie -- a to i tak jest dużo)
http://mikaelkoskinen.net/post/windows-phone-caliburn-micro-split-app-multiple-assemblies.aspx