Обновлять сразу несколько экземпляров Realm?

Я использую установку, в которой каждый Presenter это сохраняется Fragment имеет свой Realm пример. Однако по сути это означает, что все Царства находятся в главном потоке.

Теперь это также означает, что если я хочу изменить Царство, мне нужно либо сделать это в основном потоке (что хорошо для небольших наборов данных, но я не очень хочу делать это с большими наборами данных), или я необходимо сделать это в фоновом потоке и обновить каждый экземпляр Realm за один раз (что возможно при простом событии для шины событий).

public enum SingletonBus {
    INSTANCE;

    private static String TAG = SingletonBus.class.getSimpleName();

    private Bus bus;

    private boolean paused;

    private final Vector<Object> eventQueueBuffer = new Vector<>();

    private Handler handler = new Handler(Looper.getMainLooper());

    private SingletonBus() {
        this.bus = new Bus(ThreadEnforcer.ANY);
    }

    public <T> void postToSameThread(final T event) {
        bus.post(event);
    }

    public <T> void postToMainThread(final T event) {
        try {
            if(paused) {
                eventQueueBuffer.add(event);
            } else {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            bus.post(event);
                        } catch(Exception e) {
                            Log.e(TAG, "POST TO MAIN THREAD: BUS LEVEL");
                            throw e;
                        }
                    }
                });
            }
        } catch(Exception e) {
            Log.e(TAG, "POST TO MAIN THREAD: HANDLER LEVEL");
            throw e;
        }
    }

    public <T> void register(T subscriber) {
        bus.register(subscriber);
    }

    public <T> void unregister(T subscriber) {
        bus.unregister(subscriber);
    }

    public boolean isPaused() {
        return paused;
    }

    public void setPaused(boolean paused) {
        this.paused = paused;
        if(!paused) {
            Iterator<Object> eventIterator = eventQueueBuffer.iterator();
            while(eventIterator.hasNext()) {
                Object event = eventIterator.next();
                postToMainThread(event);
                eventIterator.remove();
            }
        }
    }
}

А также

SingletonBus.INSTANCE.postToMainThread(new RealmRefreshEvent());

@Subscribe
public void onRealmRefreshEvent(RealmRefreshEvent e) {
    this.realm.refresh();
}

Но если предположить, что в главном потоке открыто около 5-7 экземпляров областей (поскольку у каждого докладчика есть свои открытые области, но они не уничтожены), я беспокоюсь о производительности и / или использовании памяти.

Итак, я думаю, у меня есть два вопроса,

1.) Является ли плохой практикой / сильно ресурсоемким иметь несколько открытых экземпляров Realm в главном потоке?

2.) Насколько ресурсоемким является обновление нескольких Сфер в одном потоке с глобальным refresh событие?

2 ответа

Решение

Realm использует внутренний кэш ThreadLocal. Файл Realm, поэтому он практически бесплатный Realm.getInstance() в каждой деятельности / фрагменте / докладчике у вас есть. Первый звонок Realm.getInstance() будет стоить немного, так как база данных должна быть открыта и проверена схема, но после этого это просто будет стоить поиск в кэше.

Кэш подсчитывает ссылки, поэтому собственные ресурсы будут освобождены только после закрытия всех экземпляров. Это означает, что может быть полезно хранить как минимум один открытый экземпляр как можно дольше.

Это также означает, что когда вы обновляете 1 из ваших открытых экземпляров, все они обновляются автоматически.

Возможный способ иметь открытую область в любое время, пока приложение активно.

public class BaseActivity extends AppCompatActivity {
    private CustomApplication customApplication;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        customApplication = (CustomApplication)getApplication();
        if(savedInstanceState == null) {
            customApplication.incrementActivityCounter();
        }
    }

    @Override
    protected void onDestroy() {
        if(isFinishing()) {
            customApplication.decrementActivityCounter();
        }
        super.onDestroy();
    }
}

public class CustomApplication extends Application {
    public static final String TAG = CustomApplication.class.getSimpleName();

    private volatile int activityCounter = 0;

    private Realm realm;

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "Application onCreate() called.");
        initializeRealm();
    }

    public void incrementActivityCounter() {
        if (activityCounter == 0) {
            Log.d(TAG, "Increment: Activity counter was 0, initializing Realm.");
            if(realm == null) {
                initializeRealm();
            }
        }
        activityCounter++;
        Log.d(TAG, "Increment: Activity counter incremented to " + activityCounter + ".");
    }

    public void decrementActivityCounter() {
        activityCounter--;
        Log.d(TAG, "Decrement: Activity counter decremented to " + activityCounter + ".");
        if(activityCounter == 0) {
            realm.close();
            realm = null;
            Log.d(TAG, "Decrement: Activity counter was 0, closed realm.");
        }
    }

    private void initializeRealm() {
        realm = Realm.getInstance(this);
        Log.d(TAG, "Realm initialized.");
    }

    public Realm getRealm() {
        return realm;
    }

    public int getActivityCounter() {
        return activityCounter;
    }

    public void setActivityCounter(int activityCounter) {
        this.activityCounter = activityCounter; //process death
    }
}

А потом

public class BaseActivity
        extends AppCompatActivity {
   @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("activityCounter", ((CustomApplication) getApplication()).getActivityCounter());
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        int activityCounter = savedInstanceState.getInt("activityCounter");
        ((CustomApplication) getApplication()).setActivityCounter(activityCounter); //fix process death initializing activity counter to 0
        Log.d(TAG, "Reset activity counter in application after process death to [" + activityCounter + "]");
    }
}
Другие вопросы по тегам