ホーム > Expression Blend > Windows Phone 7 のはてなフォトライフビューワを作る

Windows Phone 7 のはてなフォトライフビューワを作る (前編)

伊勢 シン@スマートフォン勉強会[著], わにちゃん@ExpressionTech.jp[編集]

Reactive Extensions (Rx) で取得するプログラムを書き直す

というわけで、非同期処理でテキストをダウンロードするため、WebClient を使ってダウンロードすることになるのですが、非同期処理と言えば id:shiba-yan が紹介してくれた Reactive Extensions (Rx)!

Windows Phone 7 と Reactive Extensions の不文律

早速このプログラムをRxで書き直してみたいと思います。

まず、必要なアセンブリ参照を先ほどSystem.Xml.Linqを追加したときと同じ要領で追加します。追加するのは以下の2つです。

  • Microsoft.Phone.Reactive
  • System.Observable

次に、MainPage.xaml.cs 先頭にある using の並んでいるところの末尾行に1行追加します。

using Microsoft.Phone.Reactive;

そしてLoadImageListBoxを修正していきます。まず、WebClientを用意します。

WebClient c = new WebClient();

次に、Rxの処理を書いていきます。Rxはとっつきにくいですが、順を追って書いていけば簡単です。ではいきましょう。

Rxの処理はすべてObservableクラスからはじまり、どこから発火するかをFrom~で指定します。今回はダウンロード成功のDownloadStringCompletedです。

Observable.FromEvent<DownloadStringCompletedEventArgs>(c, "DownloadStringCompleted")

Selectでイベント引数から必要なデータを取得します。

    .Select(p => XDocument.Load(new StringReader(p.EventArgs.Result)))

Rxは基本的に違うスレッドで動いているので、UIのスレッドに移動するように指定して、

    .ObserveOnDispatcher()

戻り値をDoで処理させます。先ほどのデータを解析するLINQとリストのItemSourceに入れる処理にします。

    .Do(p =>
    {
        var q = from elem in p.Root.Elements()
                where elem.Name.ToString().EndsWith("item")
                select new HatenaFotolifeRssItem()
                {
                    Title = elem.Element(rssSpace + "title").Value,
                    Link = elem.Element(rssSpace + "link").Value,
                    Description = elem.Element(rssSpace + "description").Value,
                    Content = elem.Element(contentSpace + "encoded").Value,
                    Date = elem.Element(dcSpace + "date").Value,
                    ImageUrl = elem.Element(hatenaSpace + "imageurl").Value,
                    ImageUrlSmall = elem.Element(hatenaSpace + "imageurlsmall").Value,
                    ImageUrlMedium = elem.Element(hatenaSpace + "imageurlmedium").Value,
                    Syntax = elem.Element(hatenaSpace + "syntax").Value,
                    Colors = (from color in elem.Element(hatenaSpace + "colors").Elements() where color.Name == hatenaSpace + "color" select color.Value).ToArray<string>()
                };
        targetList.ItemsSource = q;
    })

最後はSubscribeで確定!

    .Subscribe();

あと、ダウンロード開始するためにWebClientのダウンロード開始すればできあがりです。

    c.DownloadStringAsync(new Uri(url));

メソッド全体ではこのようになります。*1

public void LoadImageListBox(string url, ListBox targetList)
{
    WebClient c = new WebClient();

    Observable.FromEvent<DownloadStringCompletedEventArgs>(c, "DownloadStringCompleted")
        .Select(p => XDocument.Load(new StringReader(p.EventArgs.Result)))
        .ObserveOnDispatcher()
        .Do(p =>
        {
            var q = from elem in p.Root.Elements()
                    where elem.Name.ToString().EndsWith("item")
                    select new HatenaFotolifeRssItem()
                   {
                       Title = elem.Element(rssSpace + "title").Value,
                       Link = elem.Element(rssSpace + "link").Value,
                       Description = elem.Element(rssSpace + "description").Value,
                       Content = elem.Element(contentSpace + "encoded").Value,
                       Date = elem.Element(dcSpace + "date").Value,
                       ImageUrl = elem.Element(hatenaSpace + "imageurl").Value,
                       ImageUrlSmall = elem.Element(hatenaSpace + "imageurlsmall").Value,
                       ImageUrlMedium = elem.Element(hatenaSpace + "imageurlmedium").Value,
                       Syntax = elem.Element(hatenaSpace + "syntax").Value,
                       Colors = (from color in elem.Element(hatenaSpace + "colors").Elements() where color.Name == hatenaSpace + "color" select color.Value).ToArray<string>()
                   };
            targetList.ItemsSource = q;
        })
        .Subscribe();

    c.DownloadStringAsync(new Uri(url));
}

これで再度実行します。今度はうまくいったよ、やったー!

f:id:iseebi:20110307034046p:image

INDEX

コメント

▲このページのトップへ