How To Manage Realm Instance?
I have an Activity that manage multiples fragments and nested fragment, like that : Activity -> RootFragment1 -> NestedFragment1, NestedFragment2 -&
Solution 1:
The docs say that you should open/close Realm in onCreateView()/onDestroyView()
, but in my experience the fragment lifecycle is unusually erratic, so I can show you two other approaches.
1.) open/close the Realm in Activity.onCreate()
and Activity.onDestroy()
, then share it to the fragments (and even down the view hierarchy!) using getSystemService()
.
publicclassMyActivityextendsAppCompatActivity {
Realm realm;
@OverrideprotectedvoidonCreate(Bundle bundle) {
// ...
realm = Realm.getDefaultInstance();
}
@OverrideprotectedvoidonDestroy() {
realm.close();
realm = null;
// ...
}
// -----------------------------privatestatic final StringREALM_TAG = "__REALM__";
publicstaticRealmgetRealm(Context context) {
// noinspection ResourceTypereturn (Realm)context.getSystemService(REALM_TAG);
}
@OverridepublicObjectgetSystemService(@NonNullString name) {
if(REALM_TAG.equals(name)) {
return realm;
}
returnsuper.getSystemService(name);
}
}
Then in fragment you can do
Realmrealm= MyActivity.getRealm(getActivity());
And in views you can do
Realmrealm= MyActivity.getRealm(getContext());
2.) manage the Realm lifecycle globally for the UI thread using retained fragment as lifecycle listener / activity reference counter.
/**
* Created by Zhuinden on 2016.08.16..
*/publicclassRealmManager {
privatestatic final StringTAG = "RealmManager";
staticRealm realm;
staticRealmConfiguration realmConfiguration;
publicstaticvoidinit(Context context) {
Realm.init(context);
}
publicstaticvoidinitializeRealmConfig(Context appContext) {
if(realmConfiguration == null) {
Log.d(TAG, "Initializing Realm configuration.");
setRealmConfiguration(newRealmConfiguration.Builder(appContext).initialData(newRealmInitialData())
.deleteRealmIfMigrationNeeded()
.inMemory()
.build());
}
}
publicstaticvoidsetRealmConfiguration(RealmConfiguration realmConfiguration) {
RealmManager.realmConfiguration = realmConfiguration;
Realm.setDefaultConfiguration(realmConfiguration);
}
privatestatic int activityCount = 0;
publicstaticRealmgetRealm() { // use on UI thread only!return realm;
}
publicstaticvoidincrementCount() {
if(activityCount == 0) {
if(realm != null) {
if(!realm.isClosed()) {
Log.w(TAG, "Unexpected open Realm found.");
realm.close();
}
}
Log.d(TAG, "Incrementing Activity Count [0]: opening Realm.");
realm = Realm.getDefaultInstance();
}
activityCount++;
Log.d(TAG, "Increment: Count [" + activityCount + "]");
}
publicstaticvoiddecrementCount() {
activityCount--;
Log.d(TAG, "Decrement: Count [" + activityCount + "]");
if(activityCount <= 0) {
Log.d(TAG, "Decrementing Activity Count: closing Realm.");
activityCount = 0;
realm.close();
if(Realm.compactRealm(realmConfiguration)) {
Log.d(TAG, "Realm compacted successfully.");
}
realm = null;
}
}
}
In conjunction with
publicclassRealmScopeListenerextendsFragment {
publicRealmScopeListener() {
setRetainInstance(true);
RealmManager.incrementCount();
}
@OverridepublicvoidonDestroy() {
RealmManager.decrementCount();
super.onDestroy();
}
}
And
/**
* Created by Zhuinden on 2016.09.04..
*/publicclassRealmActivityextendsAppCompatActivity {
protected Realm realm;
@OverrideprotectedvoidonCreate(@Nullable Bundle savedInstanceState) {
RealmManager.init(this);
RealmManager.initializeRealmConfig(getApplicationContext());
super.onCreate(savedInstanceState);
RealmScopeListenerrealmScopeListener= (RealmScopeListener)getSupportFragmentManager().findFragmentByTag("SCOPE_LISTENER");
if(realmScopeListener == null) {
realmScopeListener = newRealmScopeListener();
getSupportFragmentManager().beginTransaction().add(realmScopeListener, "SCOPE_LISTENER").commit();
}
realm = RealmManager.getRealm();
}
}
This allows you to call RealmManager.getRealm()
for the UI thread, and its lifecycle is managed by retain fragments.
Post a Comment for "How To Manage Realm Instance?"