(我已经看过其他帖子,但他们有点过时,主要是引用领域1.x)
一直在寻找在我们的应用程序中建立领域的最佳方式。我们目前到处都是,并希望集中我们的领域实例。
在这个链接(https://medium.com/@Zhuinden/basics-of-realm-a-guide-to-using-realm-1-2-0-634471c0fe8f)中,我发现我认为这是一个伟大的全球实施,但我有2个问题:
1。这仍然适用于当前版本的域(目前为4.1)吗?
2。保留片段的目的是什么?可以在没有片段的情况下完成吗?
提前致谢!
以下链接中的相关部分:
- 制作全球Realm实例
我在我的活动中设置了一个保留的片段,它会增加当前活动的>活动计数。打开 领域如果计数器从0变为1.如果计数器关闭领域 从1到0。
import android.content.Context;
import android.util.Log;
import io.realm.Realm;
import io.realm.RealmConfiguration;
/**
* Created by Zhuinden on 2016.08.16..
*/
public class RealmManager {
static Realm realm;
static RealmConfiguration realmConfiguration;
public static void initializeRealmConfig(Context appContext) {
if(realmConfiguration == null) {
setRealmConfiguration(new RealmConfiguration.Builder(appContext)
.deleteRealmIfMigrationNeeded()
.build());
}
}
public static void setRealmConfiguration(RealmConfiguration realmConfiguration) {
RealmManager.realmConfiguration = realmConfiguration;
Realm.setDefaultConfiguration(realmConfiguration);
}
private static int activityCount = 0;
public static Realm getRealm() {
return realm;
}
public static void incrementCount() {
if(activityCount == 0) {
if(realm != null) {
if(!realm.isClosed()) {
realm.close();
}
}
realm = Realm.getDefaultInstance();
}
activityCount++;
}
public static void decrementCount() {
activityCount--;
if(activityCount <= 0) {
activityCount = 0;
realm.close();
Realm.compactRealm(realmConfiguration);
realm = null;
}
}
}
setRealmConfiguration()方法是可以替换的 使用配置的测试测试的默认配置 inMemory()境界。如果您使用此功能,则可以轻松计算活动 使用保留片段的引用!
public class BooksScopeListener extends Fragment { // could go to base class
public BooksScopeListener() {
setRetainInstance(true);
RealmManager.incrementCount();
}
@Override
public void onDestroy() {
RealmManager.decrementCount();
super.onDestroy();
}
}
public class BooksActivity extends AppCompatActivity {
Realm realm;
@Override
protected void onCreate(Bundle savedInstanceState) {
RealmManager.initializeRealmConfig(getApplicationContext()); // could go to base class
super.onCreate(savedInstanceState);
BooksScopeListener fragment = (BooksScopeListener) getSupportFragmentManager().findFragmentByTag("SCOPE_LISTENER"); // could go to base class
if(fragment == null) {
fragment = new BooksScopeListener();
getSupportFragmentManager().beginTransaction().add(fragment, "SCOPE_LISTENER").commit();
}
//get realm instance
realm = RealmManager.getRealm();
Ta-dah,现在您可以随意访问RealmManager.getRealm() UI线程。或者只是@Inject从一个模块。 (别忘了 每个活动或片段的范围方法也有效,我更喜欢 这个是因为我在@Subcomponents上使用了@Singleton组件。
答案 0 :(得分:2)
我在大约一年前写过那篇文章,虽然这为 UI线程创建了一个全局Realm,但你无法在任何线程上使用它。如果你在后台线程上打开/关闭Realm,你仍然需要传递Realm作为方法参数。
- 这是否仍然适用于当前版本的领域(目前为4.1)?
醇>
领域生命周期管理仍然是您需要做的事情,即使对于4.1.0也是如此,就像在1.2.0中一样。这是一件从未改变过的事情:)
- 保留片段的目的是什么?可以在没有片段的情况下完成吗?
醇>
添加保留的片段,这样您就不会因为旋转屏幕而关闭/重新打开Realm;最近你可以使用ViewModel
的构造函数+ onCleared()
方法执行此操作。
我刚刚发现保留的片段是最值得信赖的监听生命周期的方式,而不会改变生命周期回调的配置变化。
本文中显示的RealmManager
仅负责UI线程上的自动生命周期管理。如果在UI线程上使用,它仍然可以正常工作。事实上,无论如何,对于UI线程,这仍然是我在下面的例子中打开/关闭的地方。
如果你想要跨线程的Realm的单例管理器类,一个起点就是使用下面的类(一点概念证明,因为我还没有在生产中使用它,但是嘿):
public class RealmManager {
private final ThreadLocal<Realm> localRealms = new ThreadLocal<>();
/**
* Opens a reference-counted local Realm instance.
*
* @return the open Realm instance
*/
public Realm open() {
checkDefaultConfiguration();
Realm realm = Realm.getDefaultInstance();
if(localRealms.get() == null) {
localRealms.set(realm);
}
return realm;
}
/**
* Returns the local Realm instance without adding to the reference count.
*
* @return the local Realm instance
* @throws IllegalStateException when no Realm is open
*/
public Realm get() {
Realm realm = localRealms.get();
if(realm == null) {
throw new IllegalStateException(
"No open Realms were found on this thread.");
}
return realm;
}
/**
* Closes local Realm instance, decrementing the reference count.
*
* @throws IllegalStateException if there is no open Realm.
*/
public void close() {
checkDefaultConfiguration();
Realm realm = localRealms.get();
if(realm == null) {
throw new IllegalStateException(
"Cannot close a Realm that is not open.");
}
realm.close();
// noinspection ConstantConditions
if(Realm.getLocalInstanceCount(Realm.getDefaultConfiguration()) <= 0) {
localRealms.set(null);
}
}
}
这种方式实际上可以使用RealmManager
类作为@Provides @Singleton RealmManager realmManager()
提供的单一入口点,并从open()
分离get()
,从而允许您使用开放给定线程的Realm实例(如果它已经打开),没有永远无法关闭它的风险(因为在没有Realm.getDefaultInstance()
对的情况下调用close()
)。
然后对于后台线程,您将使用
try {
realmManager.open();
...
} finally {
realmManager.close();
}
在其他方法中你可以做到
Realm realm = realmManager.get();
对于UI线程,您可以像往常一样使用保留的片段(或Activity / Fragment onCreate()
/ onDestroy()
),但也使用open/close
。
通过这种方式,您可以在一个地方管理Realm生命周期,但仍然将Realm作为线程局部变量传递,而不是全局传递(由于Realm实例是线程限制的,因此无法工作)。