1. amay077

    Posted

    amay077
Changes in title
+細かすぎて伝わらない Xamarin にして良かった事(その1)
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,120 @@
+
+それ Xamarin じゃなくて C# じゃん!とかのツッコミはナシでw
+まあ Java よりも Objective-C よりも C# がイイから選んでいるわけで。
+サンプルコードは Xamarin.Android ですが iOS でも同じです。
+
+## 1. イベントのマルチキャストができる!
+
+``setOnClickListener`` とかリスナー系が全部 ``Event`` になっているので、複数のリスナを登録可能、削除もできます。
+
+```cs:MainActivity.cs
+protected override void OnCreate(Bundle bundle)
+{
+ /** 省略 **/
+
+ Button button = FindViewById<Button>(Resource.Id.myButton);
+
+ // Label 変えます
+ button.Click += delegate
+ {
+ button.Text = string.Format("{0} clicks!", count++);
+ };
+
+ // Logcat にも出しちゃう
+ button.Click += (sender, e) => Android.Util.Log.Debug("Main", "Clicked!");
+
+ // .NET2.0 な方の書き方
+ button.Click += button_Click;
+}
+
+// Toast にも出そ
+void button_Click(object sender, EventArgs e)
+{
+ Toast.MakeText(this, "Clicked!", ToastLength.Short).Show();
+}
+```
+
+## 2. ``var`` が使える!
+
+C# なら ``var`` 使わなきゃ。
+
+```cs:using_var
+Dictionary<String, Object> map = new Dictionary<Piyo, Hoge>(); // 長いよ…
+var map = new Dictionary<Piyo, Hoge>();
+
+//Button button = FindViewById<Button>(Resource.Id.myButton);
+var button = FindViewById<Button>(Resource.Id.myButton);
+```
+
+Variant じゃないですから、念の為。
+
+## 3. Runnable がラムダ式で書ける!
+
+Android-Java では ``Activity.runOnUiThread`` や ``Handler.post`` って Runnable を受け取るようになっていて、大抵無名クラスにするので、長ったらしい記述になってしまいますが、Xamarin.Android では、Runnable に加えて ``Action`` も受け取ってくれ、これはラムダ式で書けるので非常にスッキリ書けます。
+Runnable にかぎらずラムダ式の恩恵は大きいのですが(イベントハンドラとか)。
+
+```cs:UsingLambdaInsteadOfRunnable.cs
+var button = FindViewById<Button>(Resource.Id.myButton);
+
+button.Click += (s, e) =>
+{
+ button.Text = "Progress...";
+
+ Task.Factory.StartNew(() =>
+ {
+ // Fat な処理
+ Thread.Sleep(3000);
+
+ // UIスレッドで実行
+ this.RunOnUiThread(() => button.Text = "Finished.");
+ /*// Java だとこんな長ったらしいコードが書かないといけない
+ MainActivity.this.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // hogehoge
+ }
+ }); */
+ });
+};
+```
+
+ちょっと話がそれますが、``Activity.runOnUiThread`` 自体、Android 固有の API なので、プラットフォーム依存を減らそうと思ったら ``SynchronizationContext`` を使います。
+
+```cs:UsingSynchronizationContext.cs
+var button = FindViewById<Button>(Resource.Id.myButton);
+
+var syncContext = SynchronizationContext.Current;
+button.Click += (s, e) =>
+{
+ button.Text = "Progress...";
+
+ Task.Factory.StartNew(() =>
+ {
+ // Fat な処理を別スレッドで
+ Thread.Sleep(3000);
+ }).ContinueWith(t => syncContext.Post(state =>
+ {
+ // UIスレッドでの処理
+ button.Text = "Finished.";
+ }, null));
+};
+```
+
+## 4. async/await が使える!
+
+それはそうと上のコード、async/await を使ったらたったの3行ですよ!
+Android の ``AsyncTask`` とか、iOS の GCD とか、ほぼ捨てられますよ。
+
+```cs:UsingAsyncAwait.cs
+var button = FindViewById<Button>(Resource.Id.myButton);
+
+button.Click += async (sender, e) =>
+{
+ button.Text = "Progress..."; // UIスレッド
+ await Task.Run(() => Thread.Sleep(3000)); // ワーカースレッド
+ button.Text = "Finished."; // UIスレッド
+};
+```
+
+とりあえずこんなところで。
+他にも、気づいたら書きます。