android - 打开/关闭 Realm 实例的最佳实践

标签 android android-fragments realm

我有一个 Android 应用程序,它使用了一种非常常见的设计模式:

  1. 主要 Activity 本质上是呈现对象列表 - 在小型设备上,它通过托管显示此列表的回收 View 的单个 fragment 来实现。在较大的设备上,它托管两个 fragment ,一个具有相同的对象回收 View ,另一个将在列表中选择一个对象时托管单个对象的详细信息。
  2. 在较小的设备上,当从列表中做出选择时,将启动一个 Activity ,该 Activity 承载一个 fragment ,该 fragment 利用 ViewPager 允许“滑动”对象列表,并在适当的位置编辑每个对象。

在这两种情况下,用户只能从详细信息 fragment 进行编辑。

我目前在应用程序类中初始化了我的 Realm 实例,然后在我用来保存一些管理方法的 Activity 基类中检索默认实例:

public abstract class SingleFragmentActivity extends AppCompatActivity {
    private Realm realm;
    protected abstract Fragment createFragment();

    @LayoutRes
    protected int getLayoutResId() {
        return R.layout.activity_fragment;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        realm = Realm.getDefaultInstance();
        // Initialize ProfileLab
        ProfileLab.get(realm);
        setContentView(getLayoutResId());

        FragmentManager fm = getSupportFragmentManager();
        Fragment fragment = fm.findFragmentById(R.id.fragment_container);

        if (fragment == null) {
            fragment = createFragment();
            fm.beginTransaction()
                    .add(R.id.fragment_container, fragment)
                    .commit();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if ( realm != null) {
            realm.close();
        }
    }
}

请注意,我将此 Realm 实例存储在静态类“ProfileLab”中:

// Initialize ProfileLab
ProfileLab.get(realm);

然后在更新数据的各种 fragment 中,我正在做类似的事情:

mProfile = ProfileLab.get().getProfile(profileId);
*
* do CRUD activities here for example:
*
    private void deleteProfile() {
        ProfileLab.get().deleteProfile(mProfile);
        mCallbacks.onProfileUpdated(mProfile);
    }

然后在 ProfileLab 中,它看起来像:

public boolean deleteProfile(配置文件 c){ bool retVal = true;

try {
    mRealm.beginTransaction();
    c.deleteFromRealm();

} catch (Exception e) {
    retVal = false;
} finally {
    if ( mRealm != null ) {
        if (retVal) {
            mRealm.commitTransaction();
        } else {
            mRealm.cancelTransaction();
        }

    }
}
return (retVal);

我的问题 - 在整个应用程序的使用过程中,基本上保持 Realm 实例像这样打开是不是一个问题?我在文档中注意到了这一段:

If you get a Realm instance from a thread that does not have a Looper attached, then objects from such instance will not be updated unless the waitForChange() method is called. It is important to note that having to hold on to an old version of your data is expensive in terms of memory and disk space and the cost increases with the number of versions between the one being retained and the latest. This is why it is important to close the Realm instance as soon as you are done with it in the thread.

问题是,我并没有“完成它”,因为这是在 UI 线程上,它显然在我的应用程序的整个生命周期中运行。

我不能仅仅为了原子更新而真正打开/关闭 Realm 实例,因为我需要使用初始查询的结果来显示要从中选择编辑的对象列表 - 当我最初尝试这样做时(我在 ProfileLab 本身的每个方法中打开/关闭了 Realm 对象)我的回收器适配器中出现错误,表明 Realm 已关闭...

显示使用回收器 View 的示例代码显示了在单个 Activity 级别检索/使用/关闭的 Realm ,如果我在两个简单的 Activity (托管 RecyclerView 和托管 ViewPager)之间这样做,数据会更新吗相互反射(reflect)?

最佳答案

建议在 try/catch block 中打开和关闭 Realm 。例如:

try {
 Realm realm = Realm.getDefaultInstance();
 //Use the realm instance

}catch(Exception e){
  //handle exceptions
}finally {
    realm.close();
}

这是使用时的一个基本示例。如果能在AsyncTask中关闭就更好了。

official documentation指的是如果你使用minSdkVersion >= 19Java >= 7,你不会手动关闭它。

try (Realm realm = Realm.getDefaultInstance()) {
// No need to close the Realm instance manually
}

关于android - 打开/关闭 Realm 实例的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42322284/

相关文章:

android - 如何以编程方式禁用 RecyclerView 的滚动

android - Visual Studio Mac,已签名的 Android 版本早于当前版本

java - 代码似乎阻止 xml 布局在 Android Studio 中显示

android - Android VideoView 加载器

java - 在 Android 中删除 Fragment 到底有什么作用?

android - 在哪里为要在 Android 中创建的 fragment 发出服务请求?

swift - Realm :使用 IN 运算符进行过滤

android - 如何在 Android 中清除 Realm 中的数据库

java - 如何比较 getString() string.xml 和 String Object?

swift - 如何使用 Realm 浏览器创建新的 Realm 实例