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

tfr*_*ger 5 android realm android-fragments

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

  1. 主要活动实际上是呈现对象列表-在小型设备上,它通过承载显示此列表的recyclerview的单个片段来实现。在较大的设备上,它托管两个片段,一个片段具有相同的对象回收视图,而另一个则将在列表中选择一个时托管各个对象的详细信息。
  2. 在较小的设备上,当从列表中进行选择时,将启动一个活动,该活动将托管一个片段,该片段利用ViewPager允许“轻扫”对象列表,并就地编辑每个对象。

在这两种情况下,都只允许用户从局部片段进行编辑。

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

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

// Initialize ProfileLab
ProfileLab.get(realm);
Run Code Online (Sandbox Code Playgroud)

然后在更新数据的各个片段中,我正在做类似的事情:

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

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

public boolean deleteProfile(Profile c){boolean 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);
Run Code Online (Sandbox Code Playgroud)

}

我的问题-从本质上来说,在整个应用程序使用期间保持Realm实例打开是一个问题吗?我在文档中注意到了这一段:

如果从未附加Looper的线程获取Realm实例,则除非调用了waitForChange()方法,否则不会更新该实例中的对象。重要的是要注意,就内存和磁盘空间而言,必须保留旧版本的数据非常昂贵,并且随着保留的版本与最新版本之间的版本数量增加,成本也会增加。这就是为什么在线程中完成Realm实例后立即关闭它很重要的原因。

关键是,我并没有做到这一点,因为它在UI线程上,该线程显然在我的应用程序的整个生命周期中都在运行。

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

显示使用回收站视图的示例代码显示了在各个活动级别上检索/使用/关闭的领域,如果我在两个简单的活动(托管RecyclerView和托管ViewPager)之间进行此操作,则数据更新将反映在彼此?

Chr*_*ior 1

Realm 会自动使 Looper 线程上的 Realm 保持最新。文档中的该特定行主要指后台线程。所以你的代码很好,即使onDestroy可能不会被调用。

您还可以阅读文档中的这些相关部分:

https://realm.io/docs/java/latest/#leading-realms https://realm.io/docs/java/latest/#realm-instance-lifecycle