Reputation: 1283
I have multiple fragments which are inside activities. I have called myAdapter in fragment onActivityCreate
method.
I have read too many articles for realm performance improvements, adapter management, realm usage. I open the realm in resume and close it in pause. But sometimes my realm adapter has shown empty.When I've deleted closeRealm
method, my adapter was running normally.
My error is because of overlapping openRealm and closeRealm from different adapters.
First adapter is opening -> openRealm--onCreate (time : 21:15) closing->closeRealm--onPause (time : 21:30:12)
Second adapter is opening -> openRealm--onCreate (time: 21:30:23) :: Above adapter is closing this realm
https://realm.io/docs/java/latest/#configuring-a-realm : It is important to note that Realm instances are thread singletons, meaning that the static constructor will return the same instance in response to all calls from a given thread.
I can manage realm for realm thread but can't manage ui thread. How can I create a different realm instance at the same time for ui thread? Please help me.
Realm adapter:
abstract class MyRealmRecyclerViewAdapter<T extends MyModel, VH extends RecyclerView.ViewHolder>
extends RealmRecyclerViewAdapter<MyModel, VH> {
protected Context context;
private String TAG = MyRealmRecyclerViewAdapter.class.getSimpleName();
protected Realm realm;
MyRealmRecyclerViewAdapter(@Nullable OrderedRealmCollection<T> data, Realm realm) {
super((OrderedRealmCollection<MyModel>) data, true, true);
if (data != null && !data.isManaged()) {
throw new IllegalStateException("Only use this adapter with managed RealmCollection, " +
"for un-managed lists you can just use the BaseRecyclerViewAdapter");
}
setRealm(realm);
setHasStableIds(true);
}
}
My fragment:
public class MyFragment extends Fragment {
private boolean isRealmAssignee = false;
private Realm realm;
@Override
public void onActivityCreated(Bundle bundle) {
super.onActivityCreated(bundle);
Mylog.i(TAG, " onActivityCreated");
try {
myAdapter = new MyRealmRecyclerViewAdapter<>(this,
new MyQueries().getAllItems(getRealm()),getRealm());
recyclerView.setAdapter(myAdapter);
} catch (Exception e) {
Mylog.printStackTrace(TAG + " initializeListAdapter error", e);
}
}
@Override
public void onResume() {
super.onResume();
Mylog.i(TAG, " onResume");
setRealm();
}
@Override
public void onPause() {
super.onPause();
Mylog.i(TAG, " onPause");
closeRealm();
}
public void setRealm() {
if (!isRealmAssignee && !RealmManager.checkRealm(realm)) {
this.realm = RealmManager.open();
isRealmAssignee = true;
}
}
public Realm getRealm() {
if (!RealmManager.checkRealm(realm)) {
isRealmAssignee = false;
setRealm();
}
return realm;
}
public void closeRealm() {
RealmManager.close(realm);
isRealmAssignee = false;
}
RealmManager:
public class RealmManager {
public synchronized static Realm open() {
return Realm.getDefaultInstance();
}
public synchronized static void close(Realm mRealm) {
if (checkRealm(mRealm)) {
mRealm.close();
}
}
public static boolean checkRealm(Realm realm) {
return realm != null && !realm.isClosed();
}
}
Upvotes: 0
Views: 695
Reputation: 81539
The answer to your question would be to use a ThreadLocal<Realm>
.
private final ThreadLocal<Realm> localRealms = new ThreadLocal<>();
/**
* Opens a reference-counted local Realm instance.
*
* @return the open Realm instance
*/
public Realm openLocalInstance() {
checkDefaultConfiguration();
Realm realm = Realm.getDefaultInstance(); // <-- this could use input RealmConfiguration
Realm localRealm = localRealms.get();
if(localRealm == null || localRealm.isClosed()) {
localRealms.set(realm);
}
return realm;
}
public Realm getLocalInstance() {
Realm realm = localRealms.get();
if(realm == null || realm.isClosed()) {
throw new IllegalStateException(
"No open Realms were found on this thread.");
}
return realm;
}
public void closeLocalInstance() {
checkDefaultConfiguration();
Realm realm = localRealms.get();
if(realm == null || realm.isClosed()) {
throw new IllegalStateException(
"Cannot close a Realm that is not open.");
}
realm.close();
// noinspection ConstantConditions
if(Realm.getLocalInstanceCount(Realm.getDefaultConfiguration()) <= 0) {
localRealms.set(null);
}
}
And then you could use realmManager.openLocalInstance()
and realmManager.closeLocalInstance()
from onCreateView
/onDestroyView
to manage the lifecycle, while use realmManager.getLocalInstance()
elsewhere on the given thread.
But it might just be easier to use findAllManaged*
in my library named Monarchy which handles automatic Realm lifecycle management.
Upvotes: 1