Повторное использование снимков баз данных Realm

У меня есть база данных 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 в своем проекте, но, возможно, у меня возникла проблема с настройкой необработанного каталога. Я не очень понимаю, как использовать «резидентные» области и как ссылаться на их повторное открытие, получение правильного пути и тому подобное.

Может быть, моя проблема заключается в ссылке или, возможно, я не знаю достаточно деталей для получения новых экземпляров. Может быть, я упускаю что-то фундаментальное.

Любая помощь приветствуется.


person T_Dun    schedule 27.03.2016    source источник
comment
Что такое сообщение об исключении при сбое?   -  person beeender    schedule 28.03.2016
comment
Извините, я пропустил ваш оперативный вопрос. Вот что я получаю: java.lang.NullPointerException: попытка вызвать виртуальный метод 'io.realm.RealmObjectSchema io.realm.RealmObjectSchema.addRealmListField (java.lang.String, io.realm.RealmObjectSchema)' для нулевого объекта ссылка на com.tomphyx.android.accelwear1.database.Migration.migrate(Migration.java:98)   -  person T_Dun    schedule 30.03.2016
comment
Вышеупомянутая ошибка связана с моей попыткой реализовать MigrationExample. и связано с моим непониманием схемы. Как определить и тому подобное.   -  person T_Dun    schedule 30.03.2016
comment
При попытке запустить свой собственный я получаю следующее java.lang.RuntimeException: Не удалось отправить событие: класс com.tomphyx.android.accelwear1.events.SensorUpdatedEvent для обработчика [EventHandler public void com.tomphyx.android.accelwear1.WearDataRecordFragment.onSensorUpdatedEvent (com.tomphyx.android.accelwear1.events.SensorUpdatedEvent)]: в com.squareup.otto.Bus.throwRuntimeException(Bus.java:458) должна быть указана ненулевая RealmConfiguration(Bus.java:458). Я должен был определить.   -  person T_Dun    schedule 30.03.2016


Ответы (1)


Итак, я провел некоторое время, работая над основами баз данных областей, и теперь все готово к использованию нескольких областей в одном фрагменте, сохранению и извлечению статических областей моментальных снимков моей активно меняющейся области.

Мой вопрос был основан на несколько фундаментальном непонимании определения схемы для классов моделей и способов перехода на новые версии по мере внесения изменений в эти классы моделей. Наряду с некоторыми основными непониманиями того, как и где хранятся миры.

Я также обнаружил огромное преимущество использования базы данных области в качестве метода передачи данных между фрагментами. Теперь у меня есть база данных под названием «GlobalVariables», которую я могу читать и записывать в/из любого фрагмента в моем проекте. Для меня больше нет аргументов фрагмента! или передача данных между фрагментами с помощью «действий хостинга».

Я просто открываю экземпляр GlobalVariables в любом месте, где мне нужны данные, и готово! Кроме того, я могу хранить варианты GlobalVariables в виде записей, чтобы можно было выполнять пользовательские настройки для определенного типа операции в моем приложении.

Спасибо beender, cmelchior и Realm, браво...

person T_Dun    schedule 31.03.2016
comment
Просто любопытно, вы все еще используете два Realms для снапшотов? - person beeender; 01.04.2016
comment
В моем Fragment DataEntryPlot я могу просматривать базу данных области, DataEntry, которая меняется много раз в секунду. Как только мне нравится внешний вид данных, я нажимаю кнопку Snapshot, которая выполняет Realm.writeCopyTo(exported.realm). Затем я снова открываю этот файл в Fragment MeasurePlot, чтобы выполнить анализ этого статического Realm. Если мне нравятся эти данные, я нажимаю кнопку моментального снимка MeasurePlot, которая делает Realm.writeCopyTo(uniqueFilename) для архивного хранения измерений. Работает хорошо, как осциллограф запоминающего типа. Далее я работаю над облачным / зашифрованным хранилищем для управления файлами. - person T_Dun; 02.04.2016
comment
Более конкретно, у меня есть активно меняющаяся область в DataEntryPLot, которую я экспортирую как временный файл и снова открываю в MeasurePlot. Каждый экспорт из DataEntryPlot перезаписывает временный файл. - person T_Dun; 02.04.2016
comment
Я думал о том, чтобы сохранить объект Version и связать с ним другие объекты в одном файле Realm. Но теперь я думаю, что ваше решение намного проще для сценария! - person beeender; 03.04.2016