眠いしお腹すいたし(´・ω・`)

C#関連を主に書きます。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

Xamarin.AndroidのArchitecture Componentsを試してみた。

すいません。アドベントカレンダー用にやっていた内容、落としました。

記事が内容薄くなってしまい大変申し訳なく思っております。

やろうとしていたことは、「Architecture ComponentsのWorkManagerをXamarin Androidで試してみる」という内容だったのですが、苦手な「Native Binding」にどハマりしまして、どうしてもうまく解決ができなく時間が無くなってしまいました。

既に40時間以上くらいつぎ込んでしまっているので、何とかして年内には完成させたいと思います。

ということで、代理的な内容になるのですが

現在Nugetに公開されているArchitecture Componentsのパッケージを試してみようと思います。

現在Nugetに公開されているパッケージは

NuGet Gallery | Packages matching Xamarin.Android.Arch

現在存在するArchitecuture Componentsのなかの

  • Lifecycle
  • VIewModel
  • LiveData

になります。

2017年に発表されていた中では

  • Room

は、公開されていません。

Roomは代用になるパッケージや実装があるので公開されていないのかなぁと思われます。

ただ、今年発表された

  • Navigation
  • Paging
  • WorkManager

にはRoomが依存してます。

今回試したかったWorkManagerはバックグラウンドタスクの管理コントロールを行うためのパッケージで、色々と使いどころが多そうなのでRoomの公開をして頂ければなぁと思ったりしています。

では、現在公開されている3つのパッケージを見ていきましょう。

LiveData

LiveDataはわたし的に説明するならLifeCycleを意識できるReactivePropertyというところです。

ApplicationのLifeCycyleの状態によって値を流す流さないを制御できるObservableです。

Java/KotlinではLiveDataとして使用できます。

ただXamarinのLiveDataパッケージにはGenericタイプがありません。

よってobjectで値をやり取りする感じになります。この辺は使いづらい感じです。

LiveDataはIObservable型というわけでは当然ないのですがTransformというReactive的な操作を行うクラスがあります。

Map関数はいわゆるSelelctです

Transformations.Map(LiveData data, IFunction func);

ただ、第2引数がIFunctionという使いにくい型なので

public class AnonymousFunction : Java.Lang.Object, IFunction
    {
        private readonly Func<Java.Lang.Object, Java.Lang.Object> _func;
        public AnonymousFunction(Func<Java.Lang.Object, Java.Lang.Object> func)
        {
            _func = func;
        }
        
        public Java.Lang.Object Apply(Java.Lang.Object p0) => _func(p0);
    }

こんなクラスを作っておくと良いかもしれません。

SwitchMap関数はネットワーク処理などを介して値を変換するような処理に向いているかと思います。

単純に流すだけでなく第2引数の関数が完了するまで値を通さなくする性質があるみたいです。

ViewModel

ViewModelはActivety Fragmentの生存期間を乗り越えて生きてくれるようです。

基本的にはAndroid.Arch.Lifecycle.ViewModelクラスを継承してViewModelを作成します。

ViewModelではApplicationContextやViewのインスタンスは受け取りません。リークになります。

Applicationを受け取りたい場合にはAndroidViewModelクラスを継承すると良いようです。

FragmentActivityのOnCreateにてViewModelProvidersからViewModelを作成すれば、OKです。

        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.activity_main);

            var vm1 = ViewModelProviders.Of(this).Get(Class.FromType(typeof(ProductViewModel)));

            var vm2 = ViewModelProviders
                .Of(this, new ProductViewModel.ProductViewModelFactory(this.Application, 5))
                .Get(Class.FromType(typeof(ProductViewModel)));
        }

LifeCycle

ライフサイクルは上の二つのベースとなる概念とライブラリです。

イベントとステートという2種類の機能によって、LiveDataのLifeCycle管理であったりViewModelの生存期間の管理などを行います。

ILifecycleObserverというインターフェースを実装するのですが、このILifecycleObserver、何も定義されてません。

public class MuListener : Java.Lang.Object, ILifecycleObserver
    {
        [Lifecycle.Event.OnStop]
        [Export]
        public void Stopped()
        {
            
        }

        [Lifecycle.Event.OnStart]
        [Export]
        public void Started()
        {
            
        }
    }

このような感じでAttributeを用いるようです。

このようにして様々なLifeCycleの管理させたいクラスに関数を持たせることができるようです。

そしてLifecycleOwnerというLifeCycle管理の親クラスにAddObserverすることによってLifeCycleの変化によって関数が呼び出されるようになります。

var listener = new MyListener();
 this.Lifecycle.AddObserver(listener);

基本的には2017年の最初のコンセプトは変化なく、これらの土台の上に2018年に発表されたWorkManagerとうの新しいコンポーネントが追加されたようです。

これらの手順に沿うことで、Xamarin Androidでもバグが起こりにくいアプリケーションの作成を行えるかと思われます。

ただ、LiveDataを始めとしてC#では少し扱いにくい面が見られます。

ReactiveExtensions / ReactivePropertyなどと組み合わせを行い便利にできる可能性があると思われます。

以上

本題を落としてしまい、あまり良い内容で書けませんでしたこと、申し訳なく思います。

<m(__)m>