Dagger 2 - 我应该使用单身Realm实例吗?

Duy*_*ham 1 android realm dagger-2

我正在使用Dagger 2为整个应用程序提供单例Realm实例(所有数据访问对象都使用单个域).但是,据我所知,Realm可以使用多实例Realm.getInstance(),我们必须在完成它们时关闭每个实例,如Realm docs所示:

    /**
     * Closes the Realm instance and all its resources.
     * <p>
     * It's important to always remember to close Realm instances when you're done with it in order not to leak memory,
     * file descriptors or grow the size of Realm file out of measure.
     *
     * @throws IllegalStateException if attempting to close from another thread.
     */
    @Override
    public void close() {
        if (this.threadId != Thread.currentThread().getId()) {
            throw new IllegalStateException(INCORRECT_THREAD_CLOSE_MESSAGE);
        }

        if (realmCache != null) {
            realmCache.release(this);
        } else {
            doClose();
        }
    }
Run Code Online (Sandbox Code Playgroud)

我的问题是:我应该像我一样使用单例Realm实例,还是为每个Activity/Fragment创建一个realm实例并使用realm.close()at 关闭它onDestroy()

Epi*_*rce 5

只有在给定线程上至少有1个Realm实例打开时,才能访问Managed RealmObjects(它们访问时加载延迟),但是在非looper后台线程上关闭Realm实例是非常严重的问题.

如果您从Dagger模块提供线程本地单例Realm,则该Realm实例只能在创建它的线程上访问.并且会导致从其他任何地方访问崩溃.

一种可能性是提供自己的单例类,可以打开Realm实例,如下所示:

@Singleton
public class RealmManager {
    private final ThreadLocal<Realm> localRealms = new ThreadLocal<>();

    @Inject
    public RealmManager() {
    }

    /**
     * Opens a reference-counted local Realm instance.
     *
     * @return the open Realm instance
     */
    public Realm openLocalInstance() {
        checkDefaultConfiguration();
        Realm realm = Realm.getDefaultInstance(); // <-- maybe this should be configurable
        if(localRealms.get() == null) {
            localRealms.set(realm);
        }
        return realm;
    }

    /**
     * Returns the local Realm instance without adding to the reference count.
     *
     * @return the local Realm instance
     * @throws IllegalStateException when no Realm is open
     */
    public Realm getLocalInstance() {
        Realm realm = localRealms.get();
        if(realm == null) {
            throw new IllegalStateException(
                    "No open Realms were found on this thread.");
        }
        return realm;
    }

    /**
     * Closes local Realm instance, decrementing the reference count.
     *
     * @throws IllegalStateException if there is no open Realm.
     */
    public void closeLocalInstance() {
        checkDefaultConfiguration();
        Realm realm = localRealms.get();
        if(realm == null) {
            throw new IllegalStateException(
                    "Cannot close a Realm that is not open.");
        }
        realm.close();
        // noinspection ConstantConditions
        if(Realm.getLocalInstanceCount(Realm.getDefaultConfiguration()) <= 0) {
            localRealms.set(null);
        }
    }

    private void checkDefaultConfiguration() {
        if(Realm.getDefaultConfiguration() == null) {
            throw new IllegalStateException("No default configuration is set.");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但即使这样,您也需要管理您需要的给定线程的本地实例.

public class MainActivity
        extends AppCompatActivity {
    RealmManager realmManager;

    ...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        realmManager = Injector.get().realmManager();
        realmManager.openLocalInstance();
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        ...
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        realmManager.closeLocalInstance();
    }
Run Code Online (Sandbox Code Playgroud)