使用Realm异步更新ListView

时间:2017-08-21 14:48:49

标签: java android multithreading asynchronous realm

当我将数据从realm数据库填充到listview时,我的应用程序会挂起一点 所以我打算用异步方式做,所以同时收集数据我在这里显示一个加载对话是代码 由于我的案例无法实现,因此已经提到this question

 private class YourAsyncTask extends AsyncTask<String, String, RealmResults> {

    ProgressDialog progressDialog;
    @Override
    protected void onPreExecute() {
        // start loading animation maybe?
        progressDialog = ProgressDialog.show(DictionarySscWords.this,
                "ProgressDialog",
                "Loading all words!");
    }

    @Override
    protected RealmResults doInBackground(String... params) {
        RealmConfiguration realmConfig = new RealmConfiguration.Builder(context).build();
        Realm.setDefaultConfiguration(realmConfig);
        realm = realm.getDefaultInstance();
        RealmQuery<Word> query = realm.where(Word.class);

        for (int i = 0; i < words_for_ssc[Integer.parseInt(params[0])].length; i++) {
            if (i == words_for_ssc[Integer.parseInt(params[0])].length - 1) {

                query = query.equalTo("word", words_for_ssc[Integer.parseInt(params[0])][i]);
            } else {
                query = query.equalTo("word", words_for_ssc[Integer.parseInt(params[0])][i])
                        .or();

            }

        }
        sscresult = query.findAll(); //error 1
        return sscresult;

    }

    @Override
    protected void onPostExecute(RealmResults r) {
        progressDialog.dismiss();
        list.setAdapter(new MyAdapter(sscresult)); //error 2
        realm.close();
    }
}

好的,如果有人可以解决我的应用程序没有错误,那么有两个问题

  1. 如果我尝试运行list.setAdapter(new MyAdapter(sscresult));在后台进程中,错误是: -
  2.   

    这只能在UI线程中运行

    1. 如果尝试在postExecute中运行错误: -
    2.   

      Realm从错误的线程访问。 Realm对象只能在创建它们的线程上访问。

      我无法解决此问题请帮助

2 个答案:

答案 0 :(得分:1)

您可以使用asynchronous query API in Realm在后台主题上评估您的查询。

Console.WriteLine($"The biggest value ({largest.Value}) is in column {largest.Column}.");

但如果您将private OrderedRealmCollectionChangeListener<RealmResults<User> callback = new OrderedRealmCollectionChangeListener<>() { @Override public void onChange(RealmResults<User> results, OrderedCollectionChangeSet changeSet) { if (changeSet == null) { // The first time async returns with an null changeSet. } else { // Called on every future update. } } }; private RealmResults<User> result; public void onStart() { result = realm.where(User.class).findAllAsync(); result.addChangeListener(callback); } 提供给RealmResults,那么这都是自动的。

P.S。在RealmRecyclerViewAdapter中没有关闭Realm实例就像,S级可怕的错误。请关闭非循环后台线程上的Realm实例。

具体如下:

doInBackground()

    // private class YourAsyncTask extends AsyncTask<String, String, RealmResults> {
    //
    //    ProgressDialog progressDialog;
    //    @Override
    //    protected void onPreExecute() {
    //        // start loading animation maybe?
    //        progressDialog = ProgressDialog.show(DictionarySscWords.this,
    //                "ProgressDialog",
    //                "Loading all words!");
    //    }
    //
    //    @Override
    //    protected RealmResults doInBackground(String... params) {
    //        RealmConfiguration realmConfig = new RealmConfiguration.Builder(context).build();
    //        Realm.setDefaultConfiguration(realmConfig);
    //        realm = realm.getDefaultInstance();
    //        RealmQuery<Word> query = realm.where(Word.class);
    //
    //        for (int i = 0; i < words_for_ssc[Integer.parseInt(params[0])].length; i++) {
    //            if (i == words_for_ssc[Integer.parseInt(params[0])].length - 1) {
    //
    //                query = query.equalTo("word", words_for_ssc[Integer.parseInt(params[0])][i]);
    //            } else {
    //                query = query.equalTo("word", words_for_ssc[Integer.parseInt(params[0])][i])
    //                        .or();
    //
    //            }
    //
    //        }
    //        sscresult = query.findAll(); //error 1
    //        return sscresult;
    //
    //    }
    //
    //    @Override
    //    protected void onPostExecute(RealmResults r) {
    //        progressDialog.dismiss();
    //        list.setAdapter(new MyAdapter(sscresult)); //error 2
    //        realm.close();
    //    }
    //}

答案 1 :(得分:-1)

我认为在不改变代码的情况下更清晰地解决您的问题可以在下面编写。在这种情况下,领域确实发生在doInBackground内的后台线程上。 realm实例也在创建它的线程上关闭。

现在我所做的基本上是我从WordsRealmResult提取了realm.copyFromRealm(sscresult)列表的深层副本,该副本与realm完全分离,可以移动在任何线程内部和修改。所有这些对象现在都没有领域,可以在onPostExecute中使用而不用担心。您需要修改的唯一内容是MyAdapter构造函数,它不会使用RealmResult,而是一个Words的列表,这正是您所需要的,并且可以像{{一样“进行迭代。 1}}是。

这种方法的唯一缺点是,RealmResult列表不会自动同步,因为它们已经分离,如果它们在Realm内从其他地方被改变,它们的价值将自动改变。但我很确定它不会打扰你。

我还要附上Words here的官方参考。

realm.copyFromRealm()

希望它有所帮助!