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

时间:2017-09-21 02:46:35

标签: android realm dagger-2

我使用Dagger 2为整个应用提供单例Realm实例(所有数据访问对象都使用单个域)。但是,据我所知,Realm可以使用 @NgModule({ declarations: [ MyApp, ExpansivoComponent ], imports: [ BrowserModule, IonicModule.forRoot(MyApp) ], bootstrap: [IonicApp], entryComponents: [ MyApp, ExpansivoComponent ], 进行多实例,我们必须关闭每个实例,当我们完成它时,由Realm docs提供:

Realm.getInstance()

我的问题是:我应该像我一样使用单身Realm实例,还是为每个Activity / Fragment创建一个realm实例,然后在 /** * 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(); } } 使用realm.close()关闭它?

2 个答案:

答案 0 :(得分:5)

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

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

一种可能性是提供一个可以打开Realm实例的单例类,例如this

@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.");
        }
    }
}

但即便如此,you'd need to manage the local instances for the given threads where you need them.

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();
    }

答案 1 :(得分:4)

单例实例最有可能让您陷入困境。您应该为每个活动/片段创建一个。