Reputation: 790
using this code:
public class App extends Application {
private static App instance;
@Override
public void onCreate() {
super.onCreate();
initRealmDB();
}
private void initRealmDB() {
instance = this;
Realm.init(this);
RealmConfiguration realmConfiguration = new RealmConfiguration.Builder().modules(new SimpleRealmModule()).name("RealmSample.realm").build();
Realm realm = null;
try {
realm = Realm.getInstance(realmConfiguration);
realm.setDefaultConfiguration(realmConfiguration);
} finally {
if (realm != null) {
realm.close();
}
}
}
}
**In use:**
Realm realm = Realm.getDefaultInstance();
RealmResults<OrganizationModelClass> results = realm.where(OrganizationModelClass.class).findAll();
if(realm.isInTransaction())
{
realm.cancelTransaction();
}
realm.beginTransaction();
if (results != null) {
if(membershipList != null)
{
membershipList.clear();
}
for (int i = 0; i < results.size(); i++) {
Log.d(OrganizationActivity.class.getName(), " i :" + results.get(i).getCurrent_membership_uuid());
}
}
Is this best way to use? Should i use singleton approach? If there is another good approach to fulfill this task, please share with me. i followed this https://dzone.com/articles/realm-practical-use-in-android but this code is not working with this dependency: classpath "io.realm:realm-gradle-plugin:3.3.1"
Realm realm = Realm.getInstance(SimpleRealmApp.getInstance());
Upvotes: 2
Views: 756
Reputation: 531
public RealmController(Context context) {
realm = Realm.getDefaultInstance();
}
public static RealmController with(Activity activity) {
if (instance == null) {
instance = new RealmController(activity.getApplication());
}
return instance;
}
public static RealmController with(Application application) {
if (instance == null) {
instance = new RealmController(application);
}
return instance;
}
public static RealmController getInstance() {
if (instance == null) {
instance = new RealmController(SysApplication.getAppContext());
}
return instance;
}
Upvotes: 0
Reputation: 81539
Is this best way to use?
No
Realm realm = Realm.getDefaultInstance(); // <-- opens Realm
RealmResults<OrganizationModelClass> results = realm.where(OrganizationModelClass.class).findAll();
if(realm.isInTransaction())
{
realm.cancelTransaction(); // <-- what if that transaction was important?
}
realm.beginTransaction();
if (results != null) {
if(membershipList != null)
{
membershipList.clear(); // <-- ??
}
for (int i = 0; i < results.size(); i++) {
Log.d(OrganizationActivity.class.getName(), " i :" + results.get(i).getCurrent_membership_uuid()); // <-- if the result set was modified here because of the transaction, then the RealmResults will update, and you'll skip elements
}
// <-- where is the commit?
} // <-- where is realm.close()?
Instead
try(Realm r = Realm.getDefaultInstance()) {
r.executeTransaction((realm) -> { // AS 3.0+ desugar
RealmResults<OrganizationModelClass> results = realm.where(OrganizationModelClass.class).findAll(); // <-- get in transaction
for (OrganizationModelClass model : results) { // uses snapshot() internally
Log.i(model.getClass().getName(), getCurrentMembershipUuid());
}
}
} // <-- auto-close because of try-with-resources
Should i use singleton approach?
Realm instances you open with getInstance()
/getDefaultInstance()
are thread-local and reference counted, so it is NOT suitable for being used as a singleton across the application. You need to open thread-local instances.
So on UI Thread, based on documentation:
// Setup Realm in your Application
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Realm.init(this);
RealmConfiguration realmConfiguration = new RealmConfiguration.Builder()
//.deleteIfMigrationNeeded()
.migration(new MyMigration())
.build();
Realm.setDefaultConfiguration(realmConfiguration);
}
}
// onCreate()/onDestroy() overlap when switching between activities.
// Activity2.onCreate() will be called before Activity1.onDestroy()
// so the call to getDefaultInstance in Activity2 will be fast.
public class MyActivity extends Activity {
private Realm realm;
private RecyclerView recyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
realm = Realm.getDefaultInstance();
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setAdapter(
new MyRecyclerViewAdapter(this, realm.where(MyModel.class).findAllSortedAsync(MyModelFields.ID)));
// ...
}
@Override
protected void onDestroy() {
super.onDestroy();
realm.close();
}
}
// Use onCreateView()/onDestroyView() for Fragments.
// Note that if the db is large, getting the Realm instance may, briefly, block rendering.
// In that case it may be preferable to manage the Realm instance and RecyclerView from
// onStart/onStop instead. Returning a view, immediately, from onCreateView allows the
// fragment frame to be rendered while the instance is initialized and the view loaded.
public class MyFragment extends Fragment {
private Realm realm;
private RecyclerView recyclerView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
realm = Realm.getDefaultInstance();
View root = inflater.inflate(R.layout.fragment_view, container, false);
recyclerView = (RecyclerView) root.findViewById(R.id.recycler_view);
recyclerView.setAdapter(
new MyRecyclerViewAdapter(getActivity(), realm.where(MyModel.class).findAllSortedAsync(MyModelFields.ID)));
// ...
return root;
}
@Override
public void onDestroyView() {
super.onDestroyView();
realm.close();
}
}
For background thread, see the docs:
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try (Realm realm = Realm.getDefaultInstance()) {
// No need to close the Realm instance manually
}
}
});
thread.start();
If you want to use Realm as a singleton, you have to use a class that can increment, decrement, and get instance without incrementing ref count for thread local Realms, kinda like this experiment here.
Upvotes: 2