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

时间:2017-02-19 00:31:21

标签: android android-fragments realm

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

  1. 主要活动主要是提供一个对象列表 - 在小型设备上,它通过托管显示此列表的回收站视图的单个片段来实现。在较大的设备上,它托管两个片段,一个片段具有相同的对象回收视图,另一个片段在列表中选择一个片段时将托管单个对象的详细信息。
  2. 在较小的设备上,当从列表中进行选择时,会启动一个活动,该活动托管一个片段,该片段利用ViewPager允许“滑动”整个对象列表,并编辑每个对象。
  3. 在这两种情况下,都允许用户仅从详细信息片段进行编辑。

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

    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();
            }
        }
    }
    

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

    // Initialize ProfileLab
    ProfileLab.get(realm);
    

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

    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(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);
    

    }

    我的问题 - 这是一个问题,基本上认为Realm实例在整个应用程序的使用过程中都是这样开放的吗?我在文档中注意到了这一段:

      

    如果从没有Looper的线程获得Realm实例   附加,然后不会更新来自此类实例的对象   调用waitForChange()方法。重要的是要注意到这一点   不得不坚持使用旧版本的数据是昂贵的   内存和磁盘空间以及成本随着数量的增加而增加   保留和最新版本之间的版本。这就是为什么   一旦完成,关闭Realm实例非常重要   它在线程中。

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

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

    显示使用Recycler视图的示例代码显示了在各个活动级别检索/使用/关闭的域,如果我在两个简单活动(托管RecyclerView和托管ViewPager)之间执行此操作,数据是否会更新相互反映?

2 个答案:

答案 0 :(得分:0)

Realm会自动将Looper线程上的Realms保持最新状态。文档中的特定行主要是指后台线程。所以你的代码很好,即使可能没有调用grep

您还可以阅读文档中的相关章节:

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

答案 1 :(得分:0)

建议在try / catch块中打开和关闭领域。举个例子:

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

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

这是一个基本的例子。如果你可以在 AsyncTask中关闭,它会更好。

official documentation表示如果您使用 minSdkVersion> = 19 Java> = 7 ,则无法手动关闭它。

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