У меня есть база данных Realm, которая заполняется данными несколько раз в секунду. Я просматриваю базу данных как построенные данные MPChartLib. Моя цель — сделать снимок базы данных в определенный момент времени и повторно использовать эту информацию чуть позже.
Я пробую пару подходов и зашел в тупик в обоих. Мой первый подход состоит в том, чтобы иметь вторую базу данных Realm, которую я буду заполнять информацией из первой базы данных одним нажатием кнопки. Мой второй подход заключается в том, чтобы экспортировать базу данных в файл, а затем повторно открыть ее позже.
В моем первом подходе я создаю две базы данных в onCreateView, как показано ниже. Я использую mRealm в качестве динамически изменяющегося Realm, а mSRealm — в качестве статического, который изменяется только при нажатии кнопки.
// Building a Realm instance un-persisted in memory (ie not on disk)
RealmConfiguration config1 = new RealmConfiguration.Builder(getActivity())
.name("myDynamic.realm")
.inMemory()
.build();
// Building a Realm instance on disk)
RealmConfiguration config2 = new RealmConfiguration.Builder(getActivity())
.name("myStatic.realm")
.build();
Log.i(TAG, "delete previous");
Realm.deleteRealm(config2);
Realm.deleteRealm(config1); // Clean slate
Log.i(TAG, "set default configuration");
Realm.setDefaultConfiguration(config1); // Make this Realm the default
Log.i(TAG, "define an instance for this");
mRealm = buildDatabase(config1);
mSRealm = buildDatabase(config2);
Log.i(TAG, "build a Listener for database changes");
realmListener = new RealmChangeListener() {
@Override
public void onChange() {
// Log.i(TAG, "database changed");
if (startTime != 0) {
// Log.i(TAG, "off to plot");
setData();
mChart.invalidate();
}
}
};
Log.i(TAG, "add Listener ");
mRealm.addChangeListener(realmListener);
И код buildDatabase для каждой конфигурации
public Realm buildDatabase(RealmConfiguration config){
try {
Log.i(TAG, "return database since there was not already one ");
return Realm.getInstance(config);
} catch (RealmMigrationNeededException e){
try {
Log.i(TAG, "deleted database since there was one");
Realm.deleteRealm(config);
Log.i(TAG, "return new database since there was one deleted");
return Realm.getInstance(config);
} catch (Exception ex){
Log.i(TAG, "should not ever get here");
throw ex;
}
}
}
Когда база данных mRealm завершила свою транзакцию, я проверяю, установлен ли для флага recordData значение true с помощью нажатия кнопки. если так, то я экспортирую базу данных в виде файла и/или пытаюсь обновить статический снимок базы данных до текущего состояния динамического.
// Log.i(TAG, "copy element to the database ");
mRealm.copyToRealm(entry);
// Log.i(TAG, " database has size = " + results.size());
mRealm.commitTransaction();
if (recordData) {
Log.i(TAG, "record copy to file ");
exportDatabase(mRealm);
Log.i(TAG, "record copy to static Database ");
copyToStaticDatabase(mRealm);
// Log.i(TAG, "record to singleton ");
// updateDataLab();
recordData = !recordData;
}
Чтобы экспортировать данные в файл, который я использую:
public void exportDatabase(Realm mRealm ) {
Log.i(TAG, "into export the database to a file ");
File exportRealmFile = null;
try {
// get or create an "export.realm" file
Log.i(TAG, "get or create file ");
exportRealmFile = new File(getActivity().getExternalCacheDir(), "export.realm");
// if "export.realm" already exists, delete
exportRealmFile.delete();
// copy current realm to "export.realm"
try {
Log.i(TAG, "write copy to file ");
mRealm.writeCopyTo(exportRealmFile);
} catch (java.io.IOException e) {
e.printStackTrace();
}
}catch (IOException e) {
e.printStackTrace();
}
Чтобы скопировать в статическую базу, я использую:
public void copyToStaticDatabase(Realm mRealm ){
Log.i(TAG, "get query of current state ");
RealmResults<DataEntry> result2 = mRealm.where(DataEntry.class).findAllSorted("timestamp");
Log.i(TAG, "delete old and create new static database ");
Realm mSRealm = buildDatabase(config2);
Log.i(TAG, "begin repopulating static database ");
mSRealm.beginTransaction();
for (int i = 0; i < result2.size(); i++) {
DataEntry entry = mSRealm.createObject(DataEntry.class);
entry.setX(result2.get(i).getX());
entry.setY(result2.get(i).getY());
entry.setZ(result2.get(i).getZ());
entry.setTimestamp(result2.get(i).getTimestamp());
entry.setAccuracy(result2.get(i).getAccuracy());
entry.setsTimestamp(result2.get(i).getsTimestamp());
mRealm.copyToRealm(entry);
}
Log.i(TAG, "finish static database ");
mSRealm.commitTransaction();
}
Этот код умирает в момент создания нового экземпляра mSRealm, так как «начать заполнение и т. д.» никогда не отображается в журнале. Не уверен, что я делаю неправильно там.
Log.i(TAG, "delete old and create new static database ");
Realm mSRealm = buildDatabase(config2);
Log.i(TAG, "begin repopulating static database ");
Я хотел бы перейти к новому фрагменту и использовать статическую базу данных. В onCreateView в новом фрагменте я пытаюсь создать конфигурацию, указывающую на статическое Realm:
// Building a Realm instance on disk
RealmConfiguration config = new RealmConfiguration.Builder(getActivity())
.name("myStatic.realm")
.build();
Log.i(TAG, "keep previous");
// Realm.deleteRealm(config); // Clean slate
Log.i(TAG, "set default configuration");
Realm.setDefaultConfiguration(config); // Make this Realm the default
Log.i(TAG, "define an instance for this");
mRealm = Realm.getDefaultInstance();
Однако я не могу проверить это, так как мой код останавливается при попытке скопировать. Что касается файлового подхода, я попытался работать с MigrationExampleActivity, которую я переписал как фрагмент и включил в свой проект, чтобы проверить, как выполняется миграция с помощью обновлений версии. Это станет более важным, поскольку будет важно архивировать моментальные снимки для долгосрочного использования в будущем.
Я думаю, что это способ «перезагрузить» базу данных из файла из того, что я читал по другим вопросам. Мой код снова падает в точке ниже получения нового экземпляра.
@Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
Log.i(TAG, " in onCreate View ");
View view = inflater.inflate(R.layout.activity_realm_basic_example, container, false);
rootLayout = ((LinearLayout) view.findViewById(R.id.container));
rootLayout.removeAllViews();
Log.i(TAG, " get resources of previous database ");
copyBundledRealmFile(this.getResources().openRawResource(R.raw.default1), "default1");
Log.i(TAG, " set up new configuration ");
RealmConfiguration config1 = new RealmConfiguration.Builder(getActivity())
.name("default1")
.schemaVersion(3)
.migration(new Migration())
.build();
Log.i(TAG, " get new instance ");
realm = Realm.getInstance(config1); // Automatically run migration if needed
Log.i(TAG, " got new instance ");
showStatus("Default1");
showStatus(realm);
realm.close();
return view;
}
Я пытался имитировать структуру realmjavamaster в своем проекте, но, возможно, у меня возникла проблема с настройкой необработанного каталога. Я не очень понимаю, как использовать «резидентные» области и как ссылаться на их повторное открытие, получение правильного пути и тому подобное.
Может быть, моя проблема заключается в ссылке или, возможно, я не знаю достаточно деталей для получения новых экземпляров. Может быть, я упускаю что-то фундаментальное.
Любая помощь приветствуется.