2

我正在使用一个设置,其中每个Presenter保留的Fragment都有自己的Realm实例。但是,这实质上意味着这些 Realm 都在主线程上。

现在这也意味着,如果我想修改 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 实例是不好的做法/资源密集型吗?

refresh2.) 使用全局事件在同一个线程上更新多个 Realm 的资源密集程度如何?

4

2 回答 2

2

Realm 在内部使用 ThreadLocal 缓存。领域文件,因此几乎可以免费调用Realm.getInstance()您拥有的每个活动/片段/演示者。第一次调用Realm.getInstance()会花费一点,因为必须打开数据库并验证模式,但之后它只需要缓存查找。

缓存是引用计数的,因此只有在关闭所有实例后才会释放本机资源。这意味着尽可能长时间地保留至少一个打开的实例可能是有益的。

这也意味着当您更新 1 个打开的实例时,它们都会自动更新。

于 2015-06-01T06:45:51.067 回答
2

在应用程序处于活动状态时始终拥有开放领域的一种可能方式。

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 + "]");
    }
}
于 2015-06-30T21:16:29.707 回答