我正在尝试查询我的Realm DB,以便输出将提供一个非托管对象,为此,我将RealmList
类型的对象更改为List
。
现在,事情是在addchangeListener中我将输出对象(stories
)的值设为managed
。但stories
的类型为List
。那么为什么我的stories
对象变为managed
,它应该作为unmanaged
对象。
List<story> stories = realm.where(story.class).findAllAsync();
stories.addChangeListener(new RealmChangeListener<RealmResults<story>>() {
@Override
public void onChange(RealmResults<story> storydata) {
if (storydata.size() != 0) {
madapter = new StoriesAdapter(stories, getBaseContext(), MR);
mrecyclerview.setNestedScrollingEnabled(false);
mrecyclerview.setLayoutManager(new LinearLayoutManager(getBaseContext()));
mrecyclerview.setAdapter(madapter);
}
}
});
StoriesAdapter
class StoriesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
List<story> storyList;
StoriesAdapter(List<story> storyList) {
this.storyList = storyList;
}
}
我说我的List
是managed
,因为当我尝试编写下面的代码时,我得到Cannot modify managed objects outside of a write transaction.
madapter.storyList.get(3).setTitle("Wonderland"); // where storyList is List which i am pointing to `stories`.
答案 0 :(得分:1)
List<story> stories = realm.where(story.class).findAllAsync();
因为指定类型List<story>
只是意味着您会将返回的列表视为List<story>
,但从技术上讲,它仍然是RealmResults<story>
。
stories.addChangeListener(new RealmChangeListener<RealmResults<story>>() {
下面的这行甚至不应该编译。
故事应存储在field
。
private RealmResults<story> stories;
public void ...() {
stories = ...
stories.addChangeListener(...
无论如何,所以你正在使用RealmResults,这意味着在
class StoriesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
List<story> storyList;
您提供的storyList
是RealmResults<story>
,因此调用storyList.get(...)
将返回托管的RealmObjects。
托管的RealmObjects是“暂时不可变的”,这意味着它们只能在事务中修改。通常也不建议在UI线程上运行写事务。
最简单的方法是使用realm-android-adapters
。
class StoriesAdapter extends RealmRecyclerViewAdapter<story, RecyclerView.ViewHolder> {
StoriesAdapter(OrderedRealmCollection<story> stories) {
super(stories, true, true);
}
}
当您想要修改对象时,您可以
story item = getData().get(3);
final String id = item.getId();
realm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
story changedItem = realm.where(story.class).equalTo("id", id).findFirst();
changedItem.setTitle("Wonderland");
}
});
然后Realm将处理自动更新RealmResults,story
对象和RecyclerView。
编辑:如果您打算使用非托管对象,那么您可以使用realm.copyFromRealm(results)
,除非在UI线程上进行读取。
您可以创建一个后台循环线程并从那里获取结果,但管理它可能会很棘手。幸运的是,我创建了一个名为Monarchy的库,可以让你做到这一点。
答案 1 :(得分:0)
故事是隐式管理的,原因是RealmResults
抽象地扩展了列表界面。这就是为什么铸造是可能的,在RealmResults
的相同机制下仍然优先。此外,如果您在RealmResults
上注册RealmChangeListener
,则应该直接将adapter.notifyDataSetChanged()
实例传递给适配器,这将调用<QData>
<Measure> some text here
<Answer>Answer1</Answer>
<Question>Question1</Question>
</Measure>
<Measure> some text here
<Answer>Answer1</Answer>
<Question>Question1</Question>
</Meaure>
</QData>
。否则,写入将更新RealmResults内容,并且您的适配器将被取消同步。
Realm不像SQLite或Core Data。如果您正在使用Realm,请利用实时对象。不要实现任何刷新逻辑或重新查询。始终允许当前类拥有自己的领域查询实例。
事实确实如此,Realm对象和任何子对象都不是线程安全的。它们仅限于一个线程,以确保维护原子权利。有一个内部列表,其中每个线程都有自己唯一的Realm实例。如果你想在一个线程之间传递对象 - 例如,如果你在主线程上创建一个dog对象,将它传递给后台线程,然后尝试访问一个属性 - 它将立即触发一个异常。
此外,您正在使用异步查询,它将其置于工作线程上。