読者です 読者をやめる 読者になる 読者になる

しっぽを追いかけて

ぐるぐるしながら考えています

Unity と猫の話題が中心   掲載内容は個人の私見であり、所属組織の見解ではありません

Xamarin.Forms の App Lifecycle の呼び出され方を調べたい

少し古いお話ですが、Xamarin.Forms 1.3 より App クラスに下記のアプリケーションライフサイクルイベントハンドラが追加されてます!

Working with the App Lifecycle - Xamarin

/// <summary>
/// アプリ起動時処理
/// </summary>
protected override void OnStart()
{
}

/// <summary>
/// アプリ中断時処理
/// </summary>
protected override void OnSleep()
{
}

/// <summary>
/// アプリ再開時処理
/// </summary>
protected override void OnResume()
{
}

Microsoft MVP 優待ライセンスにより、めでたく Xamarin.Android も利用できるようになったので、これらのイベントハンドラWindows Phone 8.0、iOSAndroid でどんな風に呼び出されるのか調べてみたいと思います

今回は手始めに調査のためのアプリ基盤を作ります

まずはログ出力機能を追加

/// <summary>
/// シンプルなログ出力クラス
/// </summary>
public class SimpleLogger
{
    /// <summary>
    /// ログ出力します
    /// </summary>
    /// <param name="message">出力内容</param>
    /// <param name="member">メソッド名</param>
    /// <param name="filepath">ファイルパス</param>
    public static void WriteLine(string message, [CallerMemberName] string member = "", [CallerFilePath] string filepath = "")
    {
        Debug.WriteLine(string.Format("{0}.{1}: {2}", Path.GetFileNameWithoutExtension(filepath).Split('\\').LastOrDefault(), member, message));
    }
}

C# の [CallerMemberName]、[CallerFilePath] 属性を利用して呼び出し元の情報を取得している以外はいたって普通の出力です

次は Xamarin.Forms 側の App.cs

/// <summary>
/// アプリケーション基盤クラス
/// </summary>
public class App : Application
{
    /// <summary>
    /// DI コンテナ
    /// </summary>
    public static UnityContainer Container = new UnityContainer();

    /// <summary>
    /// コンストラクタ
    /// </summary>
    public App()
    {
        this.MainPage = new NavigationPage(new TopPage());
    }

    /// <summary>
    /// アプリ起動時処理
    /// </summary>
    protected override void OnStart()
    {
        SimpleLogger.WriteLine("started.");
    }

    /// <summary>
    /// アプリ中断時処理
    /// </summary>
    protected override void OnSleep()
    {
        SimpleLogger.WriteLine("sleeped.");
    }

    /// <summary>
    /// アプリ再開時処理
    /// </summary>
    protected override void OnResume()
    {
        SimpleLogger.WriteLine("resumed.");
    }
}

DI コンテナをつけて各種イベントハンドラでログ出力してるだけ

さらにトップ画面

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="SupportLifecycle.Views.TopPage">
  
  <Button Text="Go Second Page" Clicked="OnButtonClicked"/>

</ContentPage>

クリックに反応するボタンのみ

画面の処理は・・・

/// <summary>
/// トップ画面
/// </summary>
public partial class TopPage : ContentPage
{
    /// <summary>
    /// コンストラクタ
    /// </summary>
    public TopPage()
    {
        InitializeComponent();
    }

    /// <summary>
    /// 画面表示時の処理
    /// </summary>
    protected override void OnAppearing()
    {
        SimpleLogger.WriteLine("TopPage Appearing.");

        base.OnAppearing();
    }

    /// <summary>
    /// ボタンタップ時の処理
    /// </summary>
    /// <param name="sender">イベント発行者</param>
    /// <param name="e">イベント引数</param>
    private async void OnButtonClicked(object sender, EventArgs e)
    {
        var navPage = App.Current.MainPage as NavigationPage;

        if (navPage == null)
        {
            return;
        }
        await navPage.PushAsync(new SecondPage());
    }
}

画面遷移時にログ出力と、クリックされたら次の画面に遷移させてます

そしてその次の画面

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="SupportLifecycle.Views.SecondPage">
  
  <Button Text="Open Xamarin home" Clicked="OnButtonClicked"/>

</ContentPage>

こちらもクリックできるボタンだけ!

なおコードビハインドは

/// <summary>
/// 二番目の画面
/// </summary>
public partial class SecondPage : ContentPage
{
    /// <summary>
    /// コンストラクタ
    /// </summary>
    public SecondPage()
    {
        InitializeComponent();
    }

    /// <summary>
    /// 画面表示時の処理
    /// </summary>
    protected override void OnAppearing()
    {
        SimpleLogger.WriteLine("SecondPage Appearing.");

        base.OnAppearing();
    }

    /// <summary>
    /// ボタンタップ時の処理
    /// </summary>
    /// <param name="sender">イベント発行者</param>
    /// <param name="e">イベント引数</param>
    private void OnButtonClicked(object sender, EventArgs e)
    {
        App.Container.Resolve<IOpenBrowserService>().OpenUri(@"http://www.xamarin.com");
    }
}

画面遷移時にログ出力と、クリックされたら・・・IOpenBrowserService.OpenUri を呼ぶようにしました

これは名称からわかる通り、指定の Uri ページをブラウザで開くサービスです

アプリ外部との連携確認用に追加したものですが、プラットフォーム依存処理になるので DI コンテナ経由で呼び出すようにしました

その IOpenBrowserService は

/// <summary>
/// Web ブラウザを開くサービスのインタフェース
/// </summary>
public interface IOpenBrowserService
{
    /// <summary>
    /// Web ブラウザを開く
    /// </summary>
    /// <param name="uri">Uri</param>
    void OpenUri(string uri);
}

1つしかメソッドのない単純なインタフェースです!

というわけで、ブラウザを開く処理の中身は書いてないですが DI コンテナのおかげで、ビルドエラーにもならずとりあえず動かすことはできます

次回以降で各プラットフォームでの動作を見ていこうと思います...