短時間で初めてのCouchbase Mobileアプリを開発しましょう!既存のアプリを改善させ、保存と同期を入れましょう!
Xamarinのインストールなどに関してはこちらをご参考にしてください。
The architecture and project structure of the KitchenSync application is shown in the following diagram:
このチュートリアルで共通部分並びにiOS・Android専用ロジックと実装します。各手順はworkshop_startプロジェクトにコメントがあります(プラットフォーム固有の部分は[番号]A (Android)と[番号]B (iOS)になっています)。
(1) データベースを取得します。. TaskManager初期化にこれを追加しましょう。
_db = Manager.SharedInstance.GetDatabase("kitchen-sync");
(2) これから速いクエリを作るためにインデックスを作成します。Couchbase LiteはC#関数でクエリを作ることができるMapReduceクエリを使います。それにドキュメントの変換や集計の計算などもできますが、こちらの場合は単純に日付によってのインデックスを作ります。
View view = _db.GetView("viewItemsByDate");
view.SetMap((doc, emit) => {
if(doc.ContainsKey("created_at") && doc["created_at"] is DateTime) {
emit(doc["created_at"], null);
}
}, "1");
(3) 次にLiveQueryを開始します。普通のQueryのように2番で作ったインデックスをフィルターやソートをかけることができます。しかしその上にクエリが終わった後のデータについても通知されます。そしてTaskオブジェクトを作成してUIに通知する必要があります。
_query = view.CreateQuery().ToLiveQuery();
_query.Descending = true;
_query.Changed += (sender, e) => {
if(TasksUpdated != null) {
var tasks = from row in e.Rows
select Task.FromDictionary(row.Document.Properties);
TasksUpdated(this, tasks.ToList());
}
};
_query.Start();
(4) これからUIの作成と更新によってTaskを保存する機能を入れます。作成と更新のロジックは似ていますが作成はPutProperties関数を使い、更新はUpdate関数を使います。新規TaskのIDはまだ入っていないのでそれで区別できます。以下のソースをSaveTaskに入れましょう。
if (item.ID == null) {
Document doc = _db.CreateDocument ();
doc.PutProperties (item.ToDictionary ());
item.ID = doc.Id;
} else {
Document doc = _db.GetDocument (item.ID);
doc.Update (newRevision => {
newRevision.SetUserProperties(item.ToDictionary());
return true;
});
}
(5) 保存があれば削除も必要です。既存のドキュメントを求めてnullでない場合はDelete関数を呼ぶ簡単な行動です。以下をDeleteTaskに入れましょう。
var doc = _db.GetExistingDocument (task.ID);
if(doc != null) {
doc.Delete();
}
(6A) UIに通知しなければデータの取得は無意味でしょう。Androidの場合はデータを表示するListViewのAdapterプロパティを指定することによって行います。このプロジェクトのKitchenSyncListAdapterクラスがその役割をします。すでに作ってありますので、作成さえすればよいです。MainActivityのInitItemListAdapterに以下を追加しましょう。
_listAdapter = new KitchenSyncListAdapter(ApplicationContext, Resource.Layout.list_item, Resource.Id.label, new List<Task>());
_itemListView.Adapter = _listAdapter;
(6B) iOSの場合は似ています。AndroidはKitchenSyncListAdapterと言えばiOSはDataSourceクラスを使います。DataSourceはHomeScreenControllerにあり、小さい変更で準備ができます(データが変わる際にテーブルビューを更新します)。DataSourceの初期化にこれを入れましょう。
taskMgr.TasksUpdated += (sender, e) => {
_rows = e;
controller.tableView.ReloadData();
};
(7A) チェックボックスをトグルする方法を入れましょう。最も自然なやり方はListViewのタップで行うことでしょう。OnItemClickに以下を追加しましょう。
Task task = _listAdapter.GetItem(position);
task.Checked = !task.Checked;
_taskMgr.SaveTask(task);
(7B) iOSの方もタップでトグル処理をします。TableViewDelegateのRowSelectedに以下を追加しましょう。
var task = _source.Tasks[indexPath.Row];
task.Checked = !task.Checked;
var manager = new TaskManager();
manager.SaveTask(task);
(8A) 削除に関してはAndroidの場合は長押しが一番自然でしょう。OnItemLongClickに以下を追加しましょう。
Task task = _listAdapter.GetItem(position);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
AlertDialog alert = builder.SetTitle("Delete Item?").
SetMessage("Are you sure you want to delete \"" + task.Text + "\"?").
SetPositiveButton("Yes", (sender, e) => _taskMgr.DeleteTask(task)).
SetNegativeButton("No", (sender, e) => {}).Create();
alert.Show();
(8B) しかしiOSに関してはユーザーはスワイプで削除処理を行うように慣れているでしょう。DataSourceのCommitEditingStyleに以下を追加しましょう。
if (editingStyle == UITableViewCellEditingStyle.Delete) {
taskMgr.DeleteTask (_rows[indexPath.Row]);
}
端末で実行してみましょう。リストの項目が保存されるはずです。
(9A) 同期を追加しましょう!MainActivityの上側に同期のURLを定義しま す。端末で行っている場合はパソコンのWi-Fi IPアドレスを使います(つまりlocalhost>ではない)。エミュレーターを使っている場合はlocalhostが10.0.2.2になります。以下をMainActivityに追加しましょう。
private const string SYNC_URL = "http://<YOUR_WIFI_OR_ETHERNET_IP>:4984/kitchen-sync";
(9B) 同期を追加しましょう!一旦AppDelegate.mに戻って、上側に同期のURLを定義します。端末で行っている場合はパソコンのWi-Fi IPアドレスを使います(つまりlocalhostではない)。シミュレーターを使っている場合はlocalhostでも大丈夫です。以下をHomeScreenControllerに追加しましょう。
private const string SYNC_URL = "http://<YOUR_WIFI_OR_ETHERNET_IP>:4984/kitchen-sync";
(10) 一番難しいところが無事に済みました。継続的にローカルとリモートの変更を同期するStartSync関数を入れましょう
Uri uri;
try {
uri = new Uri(syncUrl);
} catch(UriFormatException) {
Log.E("TaskManager", "Invalid URL {0}", syncUrl);
return;
}
if(_pull == null) {
_pull = _db.CreatePullReplication(uri);
_pull.Continuous = true;
_pull.Start();
}
if(_push == null) {
_push = _db.CreatePushReplication(uri);
_push.Continuous = true;
_push.Start();
}
(11A) 後は呼び出すだけです。MainActivityのOnCreateに以下を追加しましょう。
_taskMgr.StartSync(SYNC_URL);
(11B) そしてHomeScreenControllerのViewDidLoadにも。
_taskMgr.StartSync(SYNC_URL);
(12) 実行しましょう!アイテムを追加するか、チェックボックスを変更する際にコンソールにログが見れるはずです。アイテムがリストに追加されていることを確認しましょう。
(13) Sync Gateway管理者コンソールで結果を見てみましょう。ブラウザーでhttp://localhost:4985/_admin/を開いてkitchen-syncリンクを押します。Documentsページが出>てきて、全てのドキュメントをリストアップします。ドキュメントのIDを押すとそのドキ ュメントの詳細を見ることができます。
(14) 最後に、皆さんのご意見をお伺いしたいです。 アンケートにご協力をお願いします !