【问题标题】:How can I create a different realm instance at the same time for ui thread?如何为 ui 线程同时创建不同的领域实例?
【发布时间】:2018-07-13 13:50:40
【问题描述】:

我有多个在活动内部的片段。我在片段onActivityCreate 方法中调用了myAdapter。

我已经阅读了太多关于领域性能改进、适配器管理、领域使用的文章。我在简历中打开领域并在暂停中关闭它。但有时我的领域适配器显示为空。当我删除closeRealm 方法时,我的适配器运行正常。

我的错误是因为不同适配器的 openRealm 和 closeRealm 重叠。

第一个适配器正在打开-> openRealm--onCreate (时间: 21:15) 关闭->closeRealm--onPause (时间: 21:30:12)

第二个适配器正在打开 -> openRealm--onCreate (时间: 21:30:23) :: 上面的适配器正在关闭这个领域

https://realm.io/docs/java/latest/#configuring-a-realm :重要的是要注意 Realm 实例是线程单例,这意味着静态构造函数将返回相同的实例以响应来自给定线程的所有调用。

我可以管理领域线程的领域,但不能管理 ui 线程。如何为 ui 线程同时创建不同的领域实例?请帮帮我。

领域适配器:

abstract class MyRealmRecyclerViewAdapter<T extends MyModel, VH extends RecyclerView.ViewHolder>
        extends RealmRecyclerViewAdapter<MyModel, VH> {

    protected Context context;
    private String TAG = MyRealmRecyclerViewAdapter.class.getSimpleName();

    protected Realm realm;

    MyRealmRecyclerViewAdapter(@Nullable OrderedRealmCollection<T> data, Realm realm) {

        super((OrderedRealmCollection<MyModel>) data, true, true);

        if (data != null && !data.isManaged()) {
            throw new IllegalStateException("Only use this adapter with managed RealmCollection, " +
                    "for un-managed lists you can just use the BaseRecyclerViewAdapter");
        }

        setRealm(realm);
        setHasStableIds(true);
    }

}

我的片段:

    public class MyFragment extends Fragment {

        private boolean isRealmAssignee = false;
        private Realm realm;

        @Override
        public void onActivityCreated(Bundle bundle) {
            super.onActivityCreated(bundle);

            Mylog.i(TAG, " onActivityCreated");
             try {
                myAdapter = new MyRealmRecyclerViewAdapter<>(this,
                        new MyQueries().getAllItems(getRealm()),getRealm());

                recyclerView.setAdapter(myAdapter);

            } catch (Exception e) {
                Mylog.printStackTrace(TAG + " initializeListAdapter error", e);
            }
        }

      @Override
        public void onResume() {
            super.onResume();

            Mylog.i(TAG, " onResume");

            setRealm();
        }

        @Override
        public void onPause() {

            super.onPause();

            Mylog.i(TAG, " onPause");
            closeRealm();
        }

        public void setRealm() {

            if (!isRealmAssignee && !RealmManager.checkRealm(realm)) {
                this.realm = RealmManager.open();
                isRealmAssignee = true;
            }
        }

        public Realm getRealm() {

            if (!RealmManager.checkRealm(realm)) {

                isRealmAssignee = false;
                setRealm();
            }

            return realm;
        }

        public void closeRealm() {

            RealmManager.close(realm);
            isRealmAssignee = false;
        }

领域经理:

public class RealmManager {

    public synchronized static Realm open() {

        return Realm.getDefaultInstance();
    }

    public synchronized static void close(Realm mRealm) {

        if (checkRealm(mRealm)) {
            mRealm.close();
        }
    }

    public static boolean checkRealm(Realm realm) {
        return realm != null && !realm.isClosed();
    }
}

【问题讨论】:

标签: android realm realm-list realmrecyclerviewadapter


【解决方案1】:

您的问题的答案是使用ThreadLocal&lt;Realm&gt;

private final ThreadLocal<Realm> localRealms = new ThreadLocal<>();

/**
 * Opens a reference-counted local Realm instance.
 *
 * @return the open Realm instance
 */
public Realm openLocalInstance() {
    checkDefaultConfiguration();
    Realm realm = Realm.getDefaultInstance(); // <-- this could use input RealmConfiguration
    Realm localRealm = localRealms.get();
    if(localRealm == null || localRealm.isClosed()) {
        localRealms.set(realm);
    }
    return realm;
}

public Realm getLocalInstance() {
    Realm realm = localRealms.get();
    if(realm == null || realm.isClosed()) {
        throw new IllegalStateException(
                "No open Realms were found on this thread.");
    }
    return realm;
}

public void closeLocalInstance() {
    checkDefaultConfiguration();
    Realm realm = localRealms.get();
    if(realm == null || realm.isClosed()) {
        throw new IllegalStateException(
                "Cannot close a Realm that is not open.");
    }
    realm.close();
    // noinspection ConstantConditions
    if(Realm.getLocalInstanceCount(Realm.getDefaultConfiguration()) <= 0) {
        localRealms.set(null);
    }
}

然后您可以使用onCreateView/onDestroyView 中的realmManager.openLocalInstance()realmManager.closeLocalInstance() 来管理生命周期,同时在给定线程的其他位置使用realmManager.getLocalInstance()


但在我的名为 Monarchy 的库中使用 findAllManaged* 可能更容易,它处理自动领域生命周期管理。

【讨论】:

  • 非常感谢。我应该怎么做 closeThisRealm(realm) 以及如何在 localRealms 中找到
  • AFAIK,如果你调用getInstance 两次然后realm1 == realm2,并且有一个增加的引用计数器。所以不需要关闭 Realm 的特定实例,只有次数很重要(当然,它发生在当前线程上)
  • 在 openLocalInstance 4.line : if(localRealm != null &amp;&amp; !localRealm.isClosed()) {localRealms.set(realm);} 不必这样,否则是真的吗?
  • 它只是为了安全,但一般来说。一般是localRealm == null,如果你在Realm关闭的时候使用它,然后你调用open
猜你喜欢
  • 2017-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多