【问题标题】:Realm.io and asynchronous queriesRealm.io 和异步查询
【发布时间】:2015-01-06 19:14:45
【问题描述】:

我们开始在一个安卓应用项目中使用 Realm.io。但是我们不喜欢 Realm.io API 的一点是没有任何异步方式来查询数据库。在旧项目中,我们使用 DbQuery 和 Sqlite,因此我们习惯于在线程或 AsyncTask's 内进行数据库查询。但是很令人不安的是,在所有示例中,查询都是在UiThread 中进行的。这对应用程序性能来说不是一件坏事吗?我们试图在线程或 AsyncTasks 中进行查询,但是当我们在 UiThread 中访问我们的模型对象时出现错误,说我们无法在不是查询它们的线程中访问 RealObjects。这是我们的示例代码:

service.getDatabaseHelper()
            .with(getActivity()) //Context that I use to instance the Realm instance
            .onFinishQuery( new DatabaseHelper.IQueryGetCallback<UserRealm>() {
                @Override
                public void onGetResult(UserRealm[] results) {
                    for(UserRealm aUser : results){
                        //Here is where it crashes
                        Log.d("Log","Username -> "+aUser.getName());
                    }
                }
            })
            .getUsersFromDb();
//.......

//In our "DAO" class
public void getUsersFromDb(){
    new GetQueryTask() {
        @Override
        public UserRealm[] onQueryReadyToBeExecuted(Realm realmInstance) {
            RealmQuery<UserRealm> query = realmInstance.where(UserRealm.class);
            RealmResults<UserRealm> result = query.findAll();
            // TODO hacer que devuelva un array

            ArrayList<UserRealm> users = new ArrayList<UserRealm>();
            for (UserRealm u : result) {
                //Here we can read the RealObject's fine
                users.add(u);
            }
            return users.toArray(new UserRealm[users.size()]);
        }
    }.execute();
}

//Our abstract task that wraps all the instantiation-transaction behaviour
public abstract class GetQueryTask<T extends RealmObject> extends AsyncTask<Void, Void, T[]> {
    @Override
    protected T[] doInBackground(Void... params) {
        //We tried to instantiate this class in several places, here
        //Send it as parameter through the AsyncTask
        //context is set in the with(Context ctx) method.
        Realm realm = Realm.getInstance(context);
        return onQueryReadyToBeExecuted(realm);
    }

    public abstract T[] onQueryReadyToBeExecuted(Realm realmInstance);

    @Override
    protected void onPostExecute(T[] result) {
        mCallback.onExecute(result);
    }
}

我们主要关心的不是这段代码的“错误”,而是是否可以像 Realm.io 开发人员在他们的示例中那样在 UiThread 中执行查询。如果是这样的话,所有这些异步执行查询的代码将不再需要。

【问题讨论】:

  • 当您使用 Traceview 检查用于执行代码的线程时,您学到了什么?

标签: android database multithreading android-asynctask realm


【解决方案1】:

来自Realm的Christian。 您是对的,查询当前需要在使用它们的线程上运行,这可能会对 UI 线程性能产生负面影响。然而,我们敏锐地意识到这一点,并正在积极努力使跨线程移动查询结果成为可能。

也就是说,Realm 中的查询 非常快,即使对于合理的大量数据也是如此,因此即使在 UI 线程上运行时,仅加载您实际使用的数据也可以非常高效。 p>

我鼓励您尝试使用您认为合理的任何数据大小并测试您的性能(最好在较旧的设备上 :))。也可以做一些技巧,比如向键添加索引,在后台线程上进行繁重的查询,将键发送到 UI 线程并在那里重新查询它们。这是一个创可贴,但在某些情况下会起作用 - 但遗憾的是不适用于列表。

【讨论】:

  • Realm 是否有原因导致我的应用程序如此滞后?当应用程序启动时,一切似乎都很好,但经过几次使用后,它开始严重挂起。提前致谢
  • 没有任何信息,很难说。尝试运行 systrace 看看是什么原因造成的:developer.android.com/studio/profile/systrace-commandline.html
【解决方案2】:

realm 0.84 现在支持异步查询。

您可以通过将“io.realm:realm-android:0.84.0-SNAPSHOT”添加到您的 build.gradle 来尝试一下。有几个新方法

  • findAllAsync
  • findAllSortedAsync
  • findFirstAsync

您必须向 RealmResult 添加 addChangeListener(RealmChangeListener) 才能在查询完成时收到通知。

文档:https://realm.io/docs/java/latest/#asynchronous-queries

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多