вторник, 19 июня 2012 г.

Жизненный цикл в Windows 8 приложениях

Особенность Windows 8 приложений заключается в том, что в отличии от обычных, десктопных, они запускаются в полноэкранном режиме и, соответственно, пользователь не может одновременно видеть два приложения. К тому же, если приложение долго не используется, то неплохо было бы отправлять его в Sleep. Вот о все об этом мы сегодня и поговорим.


Начнем с небольшой картинки, описывающий в каких состояниях может находиться приложение Windows 8:
Итак, при старте приложения, оно находится в состоянии "Не запущено" (NotRunning). При активации приложения, перед тем как оно перейдет в состояние "Запущено" (Running), происходит показ заставки (SplachScreen). Вот с этого и начнем.
Первый пример, на показ заставки при старте приложения. На самом деле, когда мы создаем приложение в Visual Studio у нас уже есть заставка. Она представляет собой картинку находящуюся в папке Asserts с именем SplashScreen.png. У нас есть два варианта. Первый, отредактировать имеющеюся картинку, но цвет фона на котором она показывается не изменится. Следовательно этот путь не для нас. И второй вариант, через изменение файла Package.appxmanifest. В этом случае, добавляем изображение которое мы хотим показывать на заставке в проект, дважды кликаем на Package.appxmanifest и выбираем добавленное изображение, также можем задать и цвет фона:
Все, заставка у нас поменялась.
Второй пример, на то, как отследить что наше приложение перешло в состояние запущено. Для этого, у нашего приложения в файле App.xaml.cs есть соответсвующая заготовка метода с именем OnLaunched. В рамках этого метода, мы можем проверить из какого состояния мы перешли в текущее и, например, загрузить настройки нашего приложения. Вот на это и сделаем пример. При первом запуске приложения, пусть оно считывает из файла настроек одно из содержищихся там приветствий и пока.
Для этого, на главную страницу добавляем TextBlock:

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    <TextBlock x:Name="tbHello" />
Grid>
и вставляем в метод OnNavigate вот такой код:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    if (e.Parameter != null)
    {
        tbHello.Text = e.Parameter.ToString();
    }
}
На этом подготовка закончена, и в файле App.xaml.cs правим метод OnLaunched:
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
    string hello = "";           
    if (args.PreviousExecutionState == ApplicationExecutionState.NotRunning)
    {
        ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
        Random rnd = new Random(DateTime.Now.Millisecond);
        string key = "hello" + rnd.Next(3);
        if (settings.Values[key] != null)
        {
            hello = settings.Values[key].ToString();
        }               
    }          
    var rootFrame = new Frame();
    if (!rootFrame.Navigate(typeof(MainPage), hello))
    {
        throw new Exception("Failed to create initial page");
    }
    Window.Current.Content = rootFrame;
    Window.Current.Activate();
}
Как видно, ничего сложного.
Третий пример, на переключение пользователя из нашего приложения и обратно в него. Когда наше приложение находится в состоянии "Запущено", пользователь может переключатся на другие приложения, соответственно деятельность в нашем надо приостанавливать, ну а потом, по возвращению пользователя продолжать. Для примера, я сделаю приложение в котором шарик будет бегать по странице, отскакивая от границ экрана. Когда пользователь переключается в другое приложение и возвращается в текущее, пусть у него движение шарика продолжается с того же места, на котором он переключился в другое приложение.
Для примера, на главную страницу, добавим вот такую разметку:

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    <Ellipse x:Name="ball" Fill="Red" Width="50" Height="50" VerticalAlignment="Top" HorizontalAlignment="Left" />
Grid>
В коде страницы добавляем таймер и вот такой обработчик:

DispatcherTimer timer = null;
Point ballPosition;
double dx = 10, dy = 10;

void timer_Tick(object sender, object e)
{
    ballPosition = new Point(ball.Margin.Left + dx, ball.Margin.Top + dy);
    if (ballPosition.X < 0 || ballPosition.X > this.ActualWidth - ball.ActualWidth)
    {
        dx = -dx;
    }
    if (ballPosition.Y < 0 || ballPosition.Y > this.ActualHeight - ball.ActualHeight)
    {
        dy = -dy;
    }
    ball.Margin = new Thickness(ballPosition.X, ballPosition.Y, 0, 0);
}
Ну и например, в NavigateTo инициализируем timer и запускаем его:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    timer = new DispatcherTimer();
    timer.Interval = new TimeSpan(1000);
    timer.Tick += timer_Tick;
    timer.Start();
}
Если запустить приложение, то мы увидим красный шарик, который летает по экрану и стукается о его края. Но, если мы переключимся в другое приложение, а затем вернемся в наше, то шарик будет не на том месте, на котором мы его оставили, а на некотором другом. Т.к. timer продолжает работать. Но мы можем, например, в конструкторе страницы, подписавшись на соответствующие события останавливать таймер, когда пользователь прекращает работу с приложением и возобновлять работу таймера при возвращении пользователя:
public MainPage()
{
    this.InitializeComponent();
    Window.Current.VisibilityChanged += Current_VisibilityChanged;
}
void Current_VisibilityChanged(object sender, Windows.UI.Core.VisibilityChangedEventArgs e)
{
    if (e.Visible)
    {
        timer.Start();
    }
    else
    {
        timer.Stop();
    }
}
Все, теперь если мы переключимся из приложение, а потом вернемся, анимация продолжется с того же места.
Четвертый пример, на простановку приложения. Пример здесь приводить не буду, т.к. его можно посмотреть в статье про настройки приложения.

Комментариев нет:

Отправить комментарий