最近realmはDynamic Reamsを含んだrealm0.86をリリースしました。Dynamic Realmsによって私たちはRealm Schemaにアクセスし、そしてオブジェクトを作り、文字列(モデルネームとフィールドネーム)を使ってフィールドに動的にアクセスできます。
Concept
Realm browserはテーブル、構造、コンテンツを見ることに使われます。このブラウザはAndroidデバイスによって提供されるローカルホストからアクセスすることができます。
NanoHTTP
NanoHTTPは他のアプリケーションに埋め込まれた軽量のHTTPサーバーで、修正BSDライセンスの下でリリースされました。
NanoHTTPD sample
public class HelloServer extends NanoHTTPD {
public static void main(String[] args) {
ServerRunner.run(HelloServer.class);
}
public HelloServer() {
super(8080);
}
@Override
public Response serve(IHTTPSession session) {
String msg = "<html><body><h1>Hello server</h1></body></html>";
return newFixedLengthResponse(msg);
}
}
このシンプルなコードはHello server
テキストでHTMLページを作りそれはローカルホストのポート8080からアクセスできます。
DynamicRealm
最初に言ったように、Dynamic Realmsは従来のRealmsの柔軟なバージョンと言えます。Dynamic Realmsは従来のRealmで使っていた物と同じconfigurationを使えるが、どんなschema定義、migration、schemaのバージョンも無視します。
Dynamic Realmsを使ったら、モデル名とフィールド名が分かればコンテンツをアックセスすることができます。
DynamicRealmObject user = realm.createObject("User");
String name = user.getString("name");
int age = user.getString("age");
DynamicRealmは柔軟性のために型安全とパフォーマンスを犠牲にしています。
RealmBrowser
実装に関して
重要なコードだけを説明するので、フルコードを見たい場合は私のgithubリポジトリを見てください。
最初に前回のセッションからパラメーターがあるかないかチェックします。
Map<String, String> params = session.getParms();
String className = params.get("class_name");
String selectedView = params.get("selected_view");
そして、そのクラスがあるかないかチェックし、そのクラスがRealmObjectのサブクラスかじゃないかチェックします。
Class clazz = Class.forName(className);
if (RealmObject.class.isAssignableFrom(clazz)) {
// Show structure or content
}
そのクラス名から普通のqueryを実行して、resultsを取ります。
RealmResults<DynamicRealmObject> realmResults = dynamicRealm.where(simpleTableName).findAll();
RealmSchemaからフィールド名を取れます。
RealmObjectSchema realmObjectSchema = dynamicRealm.getSchema().get(simpleTableName);
Set<String> fieldNames = realmObjectSchema.getFieldNames();
今フィールドタイプを直接取れるAPIはまだ実装されていませんが、私はgithub issueを登録して、realmチームが解決してくれたので次のバージョン(0.87)のリリースに入っているはずです。
そして、フィールドタイプを取るために私は他の方法を考えて、一つ一つのオブジェクトをタイプチェックを行います。
private RealmFieldType checkRealmFieldType(Object obj) {
int nativeValue = -1;
if (obj instanceof Long || obj instanceof Integer || obj instanceof Short || obj instanceof Byte) {
nativeValue = 0;
} else if (obj instanceof Boolean) {
nativeValue = 1;
} else if (obj instanceof String) {
nativeValue = 2;
} else if (obj instanceof byte[] || obj instanceof ByteBuffer) {
nativeValue = 4;
} else if (obj == null || obj instanceof Object[][]) {
nativeValue = 5;
} else if (obj instanceof Mixed) {
nativeValue = 6;
} else if (obj instanceof Date) {
nativeValue = 7;
} else if (obj instanceof Float) {
nativeValue = 9;
} else if (obj instanceof Double) {
nativeValue = 10;
}
return RealmFieldType.fromNativeValue(nativeValue);
}
そして、さっきのresultsから一番目のオブジェクトを取って、さっき定義した機能でタイプチェックを行います。
int index = 0;
for (String fieldName : fieldNameArray) {
Object object = realmResults.get(0).get(fieldName);
realmFieldTypes[index] = checkRealmFieldType(object);
index++;
}
最後にコンテンツを取るために、テーブルを反復して、フィールドタイプによってgetter機能でvalueを取ります。
for (int i = 0; i < tableSize; i++) {
DynamicRealmObject dynamicRealmObject = realmResults.get(i);
for (int j = 0; j < columnCount; j++) {
String columnName = fieldNameArray[j];
String value = "";
switch (realmFieldTypes[j]) {
case INTEGER:
value = String.valueOf(dynamicRealmObject.getLong(columnName));
break;
case BOOLEAN:
value = String.valueOf(dynamicRealmObject.getBoolean(columnName));
break;
case FLOAT:
value = String.valueOf(dynamicRealmObject.getFloat(columnName));
break;
case DOUBLE:
value = String.valueOf(dynamicRealmObject.getDouble(columnName));
break;
case DATE:
value = dynamicRealmObject.getDate(columnName).toString();
break;
case STRING:
value = dynamicRealmObject.getString(columnName);
break;
}
}
}
使い方
このライブラリーの使い方はRealmBrowserのインスタンスを作って、RealmBrowser.start();
という機能を呼んだらRealmBrowserが始まります。ポートを設定したい場合に、パラメーターを入れてください。使い終わったら RealmBrowser.stop();
を呼んでください。
ブラウザからアックセスしたい場合に、realmBrowser.showServerAddress(this);
という機能を呼んで、logcatでRealmBrowserのaddressが表示されます。
注意:AndroidデバイスとPCやMacが同じWi-Fiに接続していないとアクセスすることができません。
最後に
このライブラリーは改善の余地がまだまだあると思います。今週中に検索機能を追加したいと今度HTML Pageの作り方も直したいと思います。
今フルコードはgithubにあります。フィードバックや問題やプルリクエストは誠にありがたいです。