我使用Realm 3.0.0作爲我的Android應用程序的數據庫。這就像一個問卷調查應用程序,用戶在應用程序內導航很多。當我使用的應用程序(來回)不斷,我得到以下錯誤:RealmError:Realm內存不足
Fatal Exception: io.realm.exceptions.RealmError: Unrecoverable error. mmap() failed: Out of memory size: 1073741824 offset: 0 in /Users/cm/Realm/realm-java/realm/realm-library/src/main/cpp/io_realm_internal_SharedRealm.cpp line 109
at io.realm.internal.SharedRealm.nativeGetSharedRealm(SharedRealm.java)
at io.realm.internal.SharedRealm.(SharedRealm.java:187)
at io.realm.internal.SharedRealm.getInstance(SharedRealm.java:229)
at io.realm.internal.SharedRealm.getInstance(SharedRealm.java:204)
at io.realm.RealmCache.createRealmOrGetFromCache(RealmCache.java:124)
at io.realm.Realm.getDefaultInstance(Realm.java:210)
現在我知道這樣做的主要原因是不打烊領域實例。但我已經多次檢查過。我確信我關閉了每一個我打開的事件。
該應用程序有許多活動和片段,它們都在onCreate
上獲得Realm實例,並在onDestroy
上關閉它。還有其他後臺網絡作業可用於上載獲取Realm實例的數據。這些作業在完成運行或取消時會關閉它們的Realm實例。
所有上述的經由匕首2得到他們的領域實例直通注射:
@Provides
@Nullable
static Realm realm(@Nullable RealmConfiguration configuration) {
if (configuration != null) {
Realm.setDefaultConfiguration(configuration);
return Realm.getDefaultInstance();
}
return null;
}
配置也以相同的匕首模塊提供。
更具體地說,調查問卷包含ViewPager中顯示的很多問題片段。每個片段被注入一個領域。給定Question Fragment中的許多交互將數據寫入數據庫(某些異步,某些阻止)。這些片段還會查詢onResume
上的數據庫以獲取其更新的數據。其中一些數據也通過realm.copyFromRealm()
從Realm中複製出來。現在,在這些情況發生的任何時候,上傳作業最有可能運行,並從數據庫讀取數據並將其上傳到服務器。上傳作業完成後,它會寫入數據庫。
我想我可以有多達7-12片段/活動在給定時刻在UI線程上持有領域引用。以及0-3其他線程(Background Jobs)上的其他參考。
此外,我在每次應用程序發佈時通過Realm.compactRealm(realmConfiguration)
壓縮我的領域數據庫(可能作爲一個單獨的問題,這似乎並不能完成它的工作)。
上面我試圖用描述性的描述我的領域用法,而沒有深入細節。現在我的問題是,當用戶過度使用應用程序(在活動/片段之間來回切換(realm注入+數據庫讀取查詢),上傳數據(realm注入+數據庫讀取&寫入查詢)),我得到以上貼出內存錯誤。
我也在使用泄漏金絲雀,它沒有檢測到任何泄漏。 (不知道它是否可以)
我是否以不應該使用Realm的方式?我應該關閉Realm實例而不是onDestroy
?我應該在一個活動中只有一個領域實例,並且擁有所有它的特性(在我的情況下最多5個)使用此實例?我可以在我的應用程序中做出什麼樣的更改,也許我的應用程序體系結構可以解決此問題?
我很感謝任何幫助,試圖解決這個問題。
編輯:我在我的後臺線程中共享領域開放關閉邏輯。
我所有的作業都將共享相同的領域使用,這是如下: 境界是通過注射懶洋洋地:
@Inject protected transient Lazy<Realm> lazyRealm;
境界對象引用在private transient Realm realm;
場舉行。我正在使用Android Priority Job Queue。當作業被添加:
@Override
public void onAdded() {
realm = lazyRealm.get();
realm.executeTransaction(realm1 -> {
//write some stuff into realm
});
realm.close();
}
和作業程序運行時的境界是retreived一次,這種方法的每一種可能的結局有realm.close()
@Override public void onRun() throws Throwable {
synchronized (syncAdapterLock) {
realm = lazyRealm.get();
Answer answer = realm.where(Answer.class).equalTo(AnswerQuery.ID, answerId).findFirst();
if (answer == null) {
realm.close();
throw new RealmException("File not found");
}
final File photoFile = new File(answer.getFilePath());
final Response response = answerService.uploadPhotoAnswer(answerId, RequestBody.create(MediaType.parse("multipart/form-data"), photoFile)).execute();
if (!response.isSuccessful()) {
realm.close();
throw new HttpError(statusCode);
}
realm.executeTransaction(realm1 -> {
answer.setSyncStatus(SyncStatus.SYNCED.getCode());
});
}
realm.close();
}
}
通話正如你可以看到,這些背景線程確實關閉他們的領域實例,就我而言。
'和0-3其他線程(背景作業)的其他參考.'我很確定「後臺作業」不關閉他們的領域。 – EpicPandaForce
@EpicPandaForce他們關閉了他們的領域。我編輯了我的問題,並添加了我的後臺作業的領域開放/關閉邏輯。 –
@EpicPandaForce我想認爲我不那麼愚蠢。我已經有了這個問題超過2個星期,並一直試圖解決它。確保我所有領域的實例都關閉是我做的第一件事。我必須在更大規模上做錯事。 –