1. morayl

    No comment

    morayl
Changes in body
Source | HTML | Preview
@@ -1,120 +1,120 @@
# はじめに
何回かRealmを利用するアプリを作成している上で、段々とこれがベストなのではないかという設計・実装を思いついたので、ここに記そうと思う。(異論・改善は大歓迎)
# 前提条件
RealmHelperというクラスを作成する。
Realmにアクセスするために作成。
1RealmObjectに対して1RealmHelperを作り、そのRealmHelperがそのオブジェクトへのアクセスを担う。
これによって、一つのクラスの肥大化を防ぎ、各Helperの責任範囲が明確になる。
# 各視点での最適解を考える
設計に当たって、2視点から必要なことを洗い出してみた。
### 必要になる使い方
Realmの利用方法にどんなものがあるかを考えてみる。
1. 単発でアクセス行いたい場合
- 画面で1回だけinsert処理を行いたい
- 一度値を読み込んで、画面に表示したいetc...
- **この場合、helperクラスはインスタンス化せず、staticメソッドで気軽に呼び出したい。Realmのopen、closeは内部でhelper側で自動的にやってほしい。**
2. RealmからRealmObjectを取得して同期したい場合
- RealmAdapterを使いたい
- リアルタイムにRealmの値を修正したいetc...
- **この場合、realm自体は終了したいときまでopenにしておきたい。ユーザー(Fragmentなど)は、必要に応じてcloseメソッドを呼び出したい。**
### クラスの実装しやすさ
実装は早く終わった方が良いし、共通処理はなるべくまとめたい。
# 考えた構成
- 抽象クラスとしてAbstractRealmHelperというクラスを用意する。
- このクラスがどのhelperクラスでもやりたい共通処理を実装している。
- 各子helperクラスはこれを継承すれば実装が楽+処理も統一される
- AbstractRealmHelper
- コンストラクタでは、Realmを生成し、フィールドに保持する。(小クラスはこのフィールドを使ってRealmにアクセスできる)
- トランザクション処理を2種類用意する
- staticなもの
- 子helperがstaticメソッドを実装しやすい時用
- transactionを引数で受取realmを生成し、closeする
- 非staticなもの
- 子helperがインスタンス化した状態で使いたいとき用
- transactionを引数にとり、フィールドに持つmRealmに対してtranscationを実行する(closeは行わない)
- フィールドのrealmをcloseする処理を定義する
- 作るhelperクラスによっては不要なもの
- RealmObjectを継承しているクラスをジェネリクスとして定義
- upsertメソッドとfindAllメソッドを作成
- (これらは私が作った時は必要だったため作成。upsert, findAll共に必ず行うわけではないので、不要かも)
# ソースコード
```java
public abstract class AbstractRealmHelper<T extends RealmObject> {
protected final Realm mRealm;
public AbstractRealmHelper() {
mRealm = getRealm();
}
static Realm getRealm() {
return Realm.getDefaultInstance();
}
protected static void executeTransactionOneShot(Realm.Transaction transaction) {
Realm realm = getRealm();
realm.executeTransaction(transaction);
realm.close();
}
public abstract void upsert(T t);
public abstract RealmResults<T> findAll();
protected void executeTransaction(Realm.Transaction transaction) {
mRealm.executeTransaction(transaction);
}
public void destroy() {
mRealm.close();
}
}
```
```java
public class ItemRealmHelper extends AbstractRealmHelper<ItemRealmObject> {
public static void insertOneShot(ItemRealmObject itemRealmObject) {
executeTransactionOneShot(insertTransaction(itemRealmObject));
}
private static Realm.Transaction insertTransaction(final ItemRealmObject itemRealmObject) {
return new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.insertOrUpdate(itemRealmObject);
}
};
}
@Override
public void upsert(final ItemRealmObject item) {
executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.copyToRealmOrUpdate(item);
}
});
}
@Override
public RealmResults<ItemRealmObject> findAll() {
return mRealm.where(ItemRealmObject.class).findAll();
}
}
```
-### 課題など
+# 課題など
- このままだと、一度closeすると再オープン出来ない(現状そういうものとして使っている)
- そのため、closeをするメソッドをcloseとせずdestroyにしている(気休め?)
- 各RealmObjectでconfigurationを分けたい場合に対応できない
- ただ、ファイル名を分けることの利点がよく分かっていないためdefaultInstanceで良い気がしている
- 複数ファイルを作っても一つのRealmObjectが修正されると結局どのRealmでもMigrationが必要になると思うので
- 本当はconfigurationも分けようと思っていたが、staticクラスのオーバーライドが出来ないため、子クラスに実装を持たせることが出来ず手詰まってしまった。(getRealmをstaticメソッドでも、インスタンスメソッドでも両方で呼びたかった。staticメソッドを諦めれば子クラスでgetRealmをオーバーライドすればよいか)