gpt4 book ai didi

android - Android 中的全局域实例

转载 作者:行者123 更新时间:2023-11-29 16:48:58 25 4
gpt4 key购买 nike

(我看过其他关于此的帖子,但它们有点过时,主要引用 Realm 1.x)

一直在寻找在我们的应用程序中建立 Realm 的最佳方式。我们目前到处都是,希望集中我们的 Realm 实例。

在这个链接 ( https://medium.com/@Zhuinden/basics-of-realm-a-guide-to-using-realm-1-2-0-634471c0fe8f ) 中,我发现我认为这是一个很好的全局实现,但我有 2 个问题:

1。这是否仍然适用于当前版本的 Realm (目前为 4.1)?

2。保留 fragment 的目的是什么?如果没有 fragment 是否可以完成?

提前致谢!

这是上面链接中的相关部分:

- Making a global Realm instance

I set up a retained fragment in my activity which increments the current active > Activity count. Open the Realm if the counter went from 0 to 1. Close the Realm if the counter went from 1 to 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;
}
}
}

The setRealmConfiguration() method is so that you can replace the default configuration from instrumentation tests with a config for an inMemory() Realm. If you use this, then you can easily count activity references using a retained fragment!

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, now you can freely access RealmManager.getRealm() anywhere for the UI thread. Or just @Inject this from a module. (Don’t forget that the scoped approach per activity or fragment works too, I just prefer this one because I used @Singleton component over @Subcomponents).

最佳答案

我大约一年前写了那篇文章,虽然它为 UI 线程 创建了一个全局 Realm ,但您不能只在任何线程。如果您在后台线程上打开/关闭 Realm,您仍然需要将 Realm 作为方法参数传递。

  1. Does this still apply to current versions of realm (currently at 4.1)?

Realm 生命周期管理仍然是您需要做的事情,同样的原则甚至适用于 4.1.0,就像它在 1.2.0 中所做的那样。这是从未真正改变过的一件事:)

  1. What's the purpose of the retained fragment and can it be done without one?

添加了保留的 fragment ,这样您就不会因为旋转屏幕而关闭/重新打开 Realm;最近,您也可以使用 ViewModel 的构造函数 + onCleared() 方法来完成此操作。

我刚刚发现保留 fragment 是监听生命周期的最值得信赖的方式,不会因配置更改而干扰生命周期回调。

文章中显示的 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 线程,您将像往常一样使用保留的 fragment (或 Activity/Fragment onCreate()/onDestroy()),但是使用 打开/关闭

通过这种方式,您可以在一个地方管理 Realm 生命周期,但仍然将 Realm 作为线程局部变量而不是全局变量传递(这是行不通的,因为 Realm 实例是线程受限的)。


关于android - Android 中的全局域实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46918440/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com