Skip to content

Instantly share code, notes, and snippets.

@hkusu
Forked from mokemokechicken/TodoModel.java
Last active September 1, 2015 15:35
Show Gist options
  • Save hkusu/8dfc3b84406bf32be567 to your computer and use it in GitHub Desktop.
Save hkusu/8dfc3b84406bf32be567 to your computer and use it in GitHub Desktop.
package io.github.hkusu.realmtodoapp;
import android.os.Handler;
import android.os.HandlerThread;
import java.util.List;
import de.greenrobot.event.EventBus;
import io.realm.Realm;
import io.realm.RealmResults;
/**
* Todoデータ操作モデルクラス
*/
public class TodoModel {
/** シングルトンインスタンス */
private static final TodoModel INSTANCE = new TodoModel();
/** Realmのインスタンス(参照用) */
private final Realm mRealmForSelect = Realm.getDefaultInstance();
/** Realmのインスタンス(更新用) */
private Realm mRealmForUpdate;
/** 更新(登録・削除)用スレッドへメッセージを送るためのハンドラ */
private final Handler mHandler;
private final RealmWrapper mRealmWrapper = new RealmWrapper();
/**
* 利用元にシングルトンインスタンスを返す
*
* @return Todoデータ操作モデルのインスタンス
*/
public static TodoModel getInstance() {
return INSTANCE;
}
/**
* コンストラクタ *外部からのインスタンス作成は禁止*
*/
private TodoModel() {
// 更新用スレッドを起動
HandlerThread handlerThread = new HandlerThread("realm");
handlerThread.start();
// ハンドラを取得
mHandler = new Handler(handlerThread.getLooper());
}
/**
* Todoデータ全件を取得(降順)
*
* @return TodoデータのList(RealmResult型であるためDBの変更内容は動的に反映される)
*/
public List<TodoEntity> get() {
return mRealmForSelect.allObjectsSorted(TodoEntity.class, TodoEntity.SORT_KEY, RealmResults.SORT_ORDER_DESCENDING);
}
/**
* idをキーにTodoデータを取得 ※現状は未使用*
*
* @param id 検索対象のTodoデータのid
* @return Todoデータ(1件)
*/
public TodoEntity getById(int id) {
return mRealmForSelect.where(TodoEntity.class)
.equalTo(TodoEntity.PRIMARY_KEY, id)
.findFirst();
}
/**
* Todoデータを登録
*
* @param todoEntity 登録するTodoデータ
* @return 成否
*/
public boolean createOrUpdate(final TodoEntity todoEntity) {
if (todoEntity.getId() == 0) {
// 登録されているTodoデータの最大idを取得し、+1 したものをidとする(つまり連番)
todoEntity.setId(getMaxId() + 1);
}
// // 別スレッドで実行
// mHandler.post(new Runnable() {
// @Override
// public void run() {
// // Realmのインスタンスはこのスレッドの中で取得する
// if (mRealmForUpdate == null) {
// mRealmForUpdate = Realm.getDefaultInstance();
// }
// // トランザクション開始
// mRealmForUpdate.beginTransaction();
// try {
// // idにプライマリキーを張ってあるため既に同一idのデータが存在していれば更新となる
// mRealmForUpdate.copyToRealmOrUpdate(todoEntity);
// // コミット
// mRealmForUpdate.commitTransaction();
// // データが変更された旨をEventBusで通知
// EventBus.getDefault().post(new ChangedEvent());
// } catch (Exception e) {
// // ロールバック
// mRealmForUpdate.cancelTransaction();
// }
// }
// });
mRealmWrapper.exec(new RealmOperation() {
@Override
public void transaction(Realm realm) {
mRealmForUpdate.copyToRealmOrUpdate(todoEntity);
}
@Override
public void afterExec(boolean success) {
if (success) {
EventBus.getDefault().post(new ChangedEvent());
}
}
});
return true;
}
/**
* idをキーにTodoデータを削除
*
* @param id 削除対象のTodoデータのid
* @return 成否
*/
public boolean removeById(final int id) {
// 別スレッドで実行
mHandler.post(new Runnable() {
@Override
public void run() {
// Realmのインスタンスはこのスレッドの中で取得する
if (mRealmForUpdate == null) {
mRealmForUpdate = Realm.getDefaultInstance();
}
// トランザクション開始
mRealmForUpdate.beginTransaction();
try {
// idに一致するレコードを削除
mRealmForUpdate.where(TodoEntity.class).equalTo(TodoEntity.PRIMARY_KEY, id).findAll().clear();
// コミット
mRealmForUpdate.commitTransaction();
// データが変更された旨をEventBusで通知
EventBus.getDefault().post(new ChangedEvent());
} catch (Exception e) {
// ロールバック
mRealmForUpdate.cancelTransaction();
}
}
});
return true;
}
/**
* Todoデータの件数を取得
*
* @return 件数
*/
public int getSize() {
return mRealmForSelect.allObjects(TodoEntity.class).size();
}
/**
* 登録されているTodoデータの最大idを取得
*
* @return 最大id
*/
private int getMaxId() {
return mRealmForSelect.where(TodoEntity.class).findAll().max(TodoEntity.PRIMARY_KEY).intValue();
}
/**
* Realmの接続を切断 *以降は利用できなくなるので注意*
*/
public void closeRealm() {
mRealmForSelect.close();
mRealmForUpdate.close();
}
/**
* EventBus用のイベントクラス
*/
public static class ChangedEvent {
// 特に渡すデータは無し
private ChangedEvent() {
}
}
}
class RealmWrapper {
/** 更新(登録・削除)用スレッドへメッセージを送るためのハンドラ */
private final Handler mHandler;
/**
* コンストラクタ *外部からのインスタンス作成は禁止*
*/
public RealmWrapper() {
// 更新用スレッドを起動
HandlerThread handlerThread = new HandlerThread("realm");
handlerThread.start();
// ハンドラを取得
mHandler = new Handler(handlerThread.getLooper());
}
public void exec(final RealmOperation operation) {
// 別スレッドで実行
mHandler.post(new Runnable() {
@Override
public void run() {
// Realmのインスタンスはこのスレッドの中で取得する
Realm realm = Realm.getDefaultInstance();
// トランザクション開始
realm.beginTransaction();
try {
operation.transaction(realm);
// コミット
realm.commitTransaction();
// この実行は MainThreadでやっても良いと思います(そのほうが親切っぽい)
operation.afterExec(true);
} catch (Exception e) {
// ロールバック
realm.cancelTransaction();
// この実行は MainThreadでやっても良いと思います(そのほうが親切っぽい)
operation.afterExec(true);
}
}
});
}
}
interface RealmOperation {
void transaction(Realm realm);
void afterExec(boolean success);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment