Experiments Never Fail

Xamarin に Reactive Extensions を導入する

昨日の ポスト を使ったのに、肝心の導入部分を説明するのを忘れていました。まあ Components から追加するだけなのですが。他のアドベントカレンダーとの掛け持ちで疲れたので、今日は軽く書いて済ませます。

Reactive Extensions を導入する #

Components で右クリック → Get more components → Reactive とかで検索 → 見つけたら Add to App で OK です。あ、この手順は .iOS でも .Android でも同じです。

使ってみましょうか #

イベントを Stream に変換する例を示してお茶を濁します。

まずこんな感じのどうでもいい画面を用意しまして、

UIButton.TouchUpInsideIObservable に変換する拡張メソッドを用意します。

public static class UIButtonExtensions
{
public static IObservable<string> ClickAsObservable(this UIButton button)
{
return Observable.FromEventPattern<EventArgs>(button, "TouchUpInside")
.Select(e => ((UIButton)e.Sender).TitleLabel.Text);
}
}

で、こんなコードを書きます。

public override void ViewDidLoad()
{
base.ViewDidLoad();

Button1.ClickAsObservable()
.Publish(_ =>
Button2.ClickAsObservable()
.Amb(
Button3.ClickAsObservable()))
.Subscribe(btnName => InvokeOnMainThread(() =>
Label1.Text = btnName + " Clicked"));
}

Observable.Amb (先にきた値を流す) #

Button1 を押すと処理の開始です。
Publish で分配して Amb は Button2 のクリックと Button3 のクリックで先に行われた方を Label1 に表示します。

Observable.Zip (どちらの値も待つ) #

Amb を Zip に変えてみます。

    Button1.ClickAsObservable()
.Publish(_ =>
Button2.ClickAsObservable()
.Zip(
Button3.ClickAsObservable(), (l,r) => new {l, r}))
.Subscribe(p => InvokeOnMainThread(() =>
Label1.Text = p.l + " and " + p.r + "Clicked"));

Zip は2つのシーケンスの結果を待ってから後続へ流します。
なので、Button2 と Button3 の両方が押されると、Label1 に表示されます。

どちらもフツーに書くとフラグ変数なんか使って実現すると思うんですけど、Rx を使うと読みやすいコードになると思います。

あと、私は Android-Java の開発では reactive4Java を使ってるんですが、あれには Observable.FromEventPattern が無い(Java のイベントの Listener はイベントのマルチキャストに対応してないから仕方ない)ので、Xamarin にすることで「完全な」Rx を使うことができて、こりゃ勉強のしがいがあるなあと思ったのでした。

何の記事でしたっけ?という感じですけど Xamarin なら Linq も Rx も使えてハッピーという事で、今日は以上です。

published at tags: Xamarin XAC13 iOS Android C# ReactiveExtensions