月別アーカイブ: 2016年7月

Xamarin、ザマリン、青空、晴れた空 -Xamarinで次世代mobile版データベースRealmを使う-

 こちらのサイトのメロディーとともにお楽しみください。

 Realmは、SQLite+ORMに変わるモバイルデータベースです。Realmは、NoSQLデータベース(非リレーショナルデータベース)ですので、オブジェクトを生成して手軽に永続化できます。
 現在、RealmはAndroidとiOSに対応しているので、Xamarinで使ってみます。Build Insiderに掲載されているXamarinでSQLiteを使うコンパクトなサンプルと同様なアプリをXamarin.Forms Portableで作成してみます。
 まず、Visual StudioでXamarin.Forms Portableなプロジェクトを作成します。
useRealm1
作成したら、NuGetパッケージマネージャで、realmを検索してインストールします。
 
 最初にModelクラスを作ります。グループ名だけを記録するGroup.csです。

using Realms;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace UseRealmApp
{
    public class Group : RealmObject
    {
        [ObjectId]
        public string ID { get; set; }
        public string Name { get; set; }
    }
}

 Realmにはいわゆるオートインクリメントな値を振る機能はありませんので、IDもStringにしてGUID値を記録することにします。
 次ぎにデータベースを操作するMemoDatabaseクラスを作成します。将来的にGroupクラスだけでなく、メモを記録するクラスなどを追加していくのでMemoDatabaseというクラス名にしました。
 GetGroups()メソッドはGroupクラスの全オブジェクトを取得します。GetGroups()メソッドの戻り値をListViewに表示します。GetGroupは指定したIDのオブジェクトを取得します。以降のメソッドについてはソースコードの下に解説を記します。

using Realms;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace UseRealmApp
{
    public class MemoDatabase
    {
        Realm realm;
        public MemoDatabase()
        {
            realm = Realm.GetInstance();
        }
        public IEnumerable<Group> GetGroups()
        {
            return realm.All<Group>().ToList();
        }
        public Group GetGroup(string id)
        {
            return realm.All<Group>()
                        .ToList()
                        .FirstOrDefault(x => x.ID == id);
        }
        public string SaveGroup(Group group)
        {
            var newGroup = realm.All<Group>()
                             .ToList()
                             .FirstOrDefault(x => x.ID == group.ID);

            using (var trans = realm.BeginWrite())
            {
                if (newGroup == null)
                {
                    newGroup = realm.CreateObject<Group>();
                    newGroup.ID = Guid.NewGuid().ToString();
                }

                newGroup.Name = group.Name;
 
                trans.Commit();
            }

            return newGroup?.ID;    // ? Nullable型
        }
        public string DeleteGroup(string id)
        {
            var item = realm.All<Group>()
                             .ToList()
                             .FirstOrDefault(x => x.ID == id);

            if (item == null)
                return null;

            using (var trans = realm.BeginWrite())
            {
                realm.Remove(item);
                trans.Commit();
            }

            return id;
        }
    }
}

 SaveGroupメソッドはオブジェクトを保存します。usingでトランザクション処理を囲みます。DeleteGroupメソッドは指定したIDのオブジェクトを削除します。

 app.csでページを表示します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace UseRealmApp
{
    public class App : Application
    {
        public App()
        {
            MainPage = new MyPage();
        }
    }
    class MyPage : ContentPage
    {

        readonly MemoDatabase _db = new MemoDatabase();

        public MyPage()
        {

            var listView = new ListView
            {
                ItemsSource = _db.GetGroups(), 
                ItemTemplate = new DataTemplate(typeof(TextCell)) 
            };
            listView.ItemTemplate.SetBinding(TextCell.TextProperty, "Name");
            listView.ItemTapped += async (s, a) => {
                var group = (Group)a.Item;
                if (await DisplayAlert("削除してよろしいですか", group.Name, "OK", "キャンセル"))
                {
                    _db.DeleteGroup(group.ID); // groupの削除
                    listView.ItemsSource = _db.GetGroups(); // リストの更新
                }
            };
            var entry = new Entry
            { 
                HorizontalOptions = LayoutOptions.FillAndExpand
            };
            var buttonAdd = new Button
            {
                WidthRequest = 60,
                Text = "追加"
            };
            buttonAdd.Clicked += (s, a) => { 
                if (!String.IsNullOrEmpty(entry.Text))
                { // Entryに文字列が入力されている場合に保存
                    var group = new Group { Name = entry.Text };
                    _db.SaveGroup(group);
                    listView.ItemsSource = _db.GetGroups(); //リストの更新
                    entry.Text = "";
                }
            };

            Content = new StackLayout
            { 
                Padding = new Thickness(0, Device.OnPlatform(20, 0, 0), 0, 0),
                Children = {
                    new StackLayout {
                        Padding = 5,
                        Orientation = StackOrientation.Horizontal,
                        Children = {entry, buttonAdd} 
                    },
                    listView 
                }
            };
        }
    }
}

 ListViewにはグループ名を一覧表示し、タップしたら削除確認のダイアログを表示します。
useRealm2
 Entryにグループ名を入力して追加ボタンをタップしたら、データベースに記録してListViewを更新します。
useRealm3
 XamarinでもRealmを簡単に使うことができました。