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

时间:2017-05-22 09:48:14

标签: android realm

尝试通过具有来自另一页面的关系(一对多)的按钮创建新对象时出现错误,使用具有回收器视图的领域将多个任务连接到一个注释(任务列表)

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.task_activity);

    final Realm mrealm = Realm.getDefaultInstance();
    RealmResults<tItem> results = mrealm.where(tItem.class).findAll();

    final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
    layoutManager.setOrientation(LinearLayoutManager.VERTICAL);


    final tData data = new tData(); 
    fbtn1 = (FloatingActionButton) findViewById(R.id.fbtn1);
    recView = (RecyclerView)findViewById(R.id.task_list);
    recView.setLayoutManager(layoutManager);


    adapter = new tAdapter(results,this);
    recView.setAdapter(adapter);
    adapter.setIconClickCallback(this);



    fbtn1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {


            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mrealm.executeTransactionAsync(new Realm.Transaction() {
                        @Override
                        public void execute(Realm realm) {
                            final RealmResults<tItem> item2 = realm.where(tItem.class).findAll();

                            tItem item = mrealm.createObject(tItem.class);
                            UUID.randomUUID()
                                    .toString();
                            taskData.add(item);
                            item.setTasks("to do list 1");
                            mrealm.copyToRealm(item);
                        }
                    });
                }
            });


            adapter.notifyDataSetChanged();
            RealmResults<tItem> tItem = mrealm.where(tItem.class).findAll();
            Log.d("john", "new task ");
            Log.d("", "path: " + mrealm.getPath());
        }
    });
}

错误指向代码的这一部分

tItem item = mrealm.createObject(tItem.class);

4 个答案:

答案 0 :(得分:0)

Realm实例是线程限制的 - 您不能从另一个线程进行查询。发生此错误,因为您在主thred上进行查询,然后尝试在异步事务中使用该查询,该查询将在另一个线程上执行:

final RealmResults<tItem> item2 = realm.where(tItem.class).findAll();

答案 1 :(得分:0)

尝试使用realm实例而不是mRealm实例创建tItem类,因为这是为异步事务创建的领域实例

tItem item = realm.createObject(tItem.class);

答案 2 :(得分:0)

您的代码应该如下所示:

Realm realm;

RealmResults<tItem> results;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.task_activity);

    realm = Realm.getDefaultInstance();
    results = realm.where(tItem.class).findAll();

    final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
    layoutManager.setOrientation(LinearLayoutManager.VERTICAL);

    fbtn1 = (FloatingActionButton) findViewById(R.id.fbtn1);
    recView = (RecyclerView)findViewById(R.id.task_list);
    recView.setLayoutManager(layoutManager);

    adapter = new tAdapter(results,this); // tAdapter extends RealmRecyclerViewAdapter
    recView.setAdapter(adapter);
    adapter.setIconClickCallback(this);

    fbtn1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            fbtn1Clicked();
        }
    });
}

private void fbtn1Clicked() {
    realm.executeTransactionAsync(new Realm.Transaction() {
        @Override
        public void execute(Realm realm) {
            final RealmResults<tItem> items = realm.where(tItem.class).findAll();
            tItem item = realm.createObject(tItem.class, UUID.randomUUID().toString();
            item.setTasks("to do list 1");
        }
    });
}

@Override
public void onDestroy() {
    super.onDestroy();
    if(realm != null) {
        realm.close();
        realm = null;
    }
}

但你原来的错误是,而不是

tItem item = mrealm.createObject(tItem.class);
你应该

tItem item = realm.createObject(tItem.class); // <-- background thread realm

答案 3 :(得分:0)

最好的办法就是在你的帖子上复制一份。如果你想在这个帖子上使用它。

此外,您应该尝试以DAO或REPOSITORY模式发出请求。 我创建了一个这样的存储库模式:

public Observable<List<T>> query(final Specification spec) {
    return Observable.create(new ObservableOnSubscribe<List<T>>() {
        @Override
        public void subscribe(@NonNull ObservableEmitter<List<T>> emitter) throws Exception {
            Log.d(TAG, "OnSubscribe ::  Thread id :"+Thread.currentThread().getId() + " name : "+Thread.currentThread().getName());
            Realm realm = Realm.getDefaultInstance();
            final RealmSpecification realmSpecification = (RealmSpecification) spec;
            RealmResults<T> res = realmSpecification.toRealmResults(realm);
            List<T> resList = realm.copyFromRealm(res);
            realm.close();
            if(res != null)
                emitter.onNext(resList);
            emitter.onComplete();
        }
    });
}

就像我可以从一个线程查询我的基地到主线程。我的所有查询都使用这些函数。