Realm不保存属性,虽然复制到Realm,但不管理对象

时间:2018-02-02 17:24:42

标签: java android database api realm

我对领域有疑问。我从API接收自定义对象。我使用改造将此对象分配给POJO对象。在这个对象中,我有一个ToDoItem对象的ArrayList extends RealmObject

我使用所有属性正确接收数据,所有内容都被正确分配。我通过我的同步算法运行它并在写入事务中将其保存到领域。但是,在realm.commit();之后检索数据时,对象的属性都是0null

方法isManaged()总是假的,即使在写入事务之后,我也不明白,因为在official documentation中表明POJO可以使用{{转换为托管对象。 1}}方法。

我已经尝试了很多东西:将GetItemResponseClass创建为RealmObject,但不可能,因为它必须扩展JSONObject以正确接收来自API的数据。我也尝试将整个列表直接写入领域,但结果是一样的。

作为旁注,可能是我的方法copyToRealm有一些逻辑错误,但我还没有调试它,因为属性总是o和null。谢谢你的帮助。

这里是我的活动代码:

syncPendingLists

这是我的ToDoItem类代码:

public class MainActivity extends AppCompatActivity{

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Realm.init(this);
    RealmConfiguration config = new RealmConfiguration.Builder().name("myrealm.realm").build();
    Realm.setDefaultConfiguration(config);


    realm = Realm.getDefaultInstance();
    RealmResults<Counter> counterList = realm.where(Counter.class).findAll();

    //setting up counterObject
    if (counterList.isEmpty()) {
        counterObject = new Counter();
        COUNTER = counterObject.getCounter();
    } else {
        counterObject = counterList.get(0);
        COUNTER = counterObject.getCounter();
    }

    initializeLists();

    //Adding the Fragment
    FragmentManager fm = getFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    ft.add(R.id.fragment_container, new DoneListFragment(), "DoneListFragment");
    ft.add(R.id.fragment_container, new PendingListFragment(), "PendingListFragment");
    ft.commit();

    RetrofitClient retrofitClient = new RetrofitClient();
    Retrofit retrofit = retrofitClient.getClient();

    mAPIInterface = retrofit.create(ToDoistAPIInterface.class);

}


public void getRemoteItems() {

    final ArrayList<ToDoItem> onlineItems = new ArrayList<ToDoItem>();
    JSONArray array = new JSONArray();
    array.put("items");

    String auxMessage = array.toString();
    mAPIInterface.getItems(RetrofitClient.TOKEN, "*", auxMessage).enqueue(new Callback<GetItemsResponseClass>() {
        @Override
        public void onResponse(Call<GetItemsResponseClass> call, Response<GetItemsResponseClass> response) {

            GetItemsResponseClass itemsResponseClass = new GetItemsResponseClass();
            itemsResponseClass = response.body();
            remoteItemsList = itemsResponseClass.getItems();

            boolean test = remoteItemsList.get(0).isManaged(); //returns false
            boolean test1 = remoteItemsList.get(0).isValid(); //returns true refers to singleton RealmObject

            syncPendingLists(pendingItemList, remoteItemsList);

        }
        @Override
        public void onFailure(Call<GetItemsResponseClass> call, Throwable t) {
            Snackbar.make(floatingButton, "Ups - Couldn't sync items, next time, I promise", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });
}


 private void initializeLists() {
        RealmResults<ToDoItem> realmToDoItemPendingList = realm.where(ToDoItem.class).equalTo("checkedOffline", false).findAll();
        initializingArrayListFromDB(realmToDoItemPendingList, pendingItemList);
        RealmResults<ToDoItem> realmToDoItemDoneList = realm.where(ToDoItem.class).equalTo("checkedOffline", true).findAll();
        initializingArrayListFromDB(realmToDoItemDoneList, doneItemList);
    }
 private void initializingArrayListFromDB(RealmResults<ToDoItem> realmToDoItemPendingList, ArrayList<ToDoItem> arrayList) {
        int h;
        for (h = 0; h < realmToDoItemPendingList.size(); h++) {
            arrayList.add(realmToDoItemPendingList.get(h));
        }
    }

 public void syncPendingLists(ArrayList<ToDoItem> offlinePendingList, ArrayList<ToDoItem> onlinePendingList) {
     //is my sync algorithm, the important part is the for loop at the end of this method
        boolean hasMatch = false;
        boolean itemChanged = false;

        Date offlineDate = null;
        Date onlineDate = null;

        if (!offlinePendingList.isEmpty()) {
            for (ToDoItem item1 : offlinePendingList) {
                if (item1.getId() < 10000) {
                    try {
                        createNewRemoteItem(item1);
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                } else {
                    for (int i = 0; i < onlinePendingList.size(); i++) {

                        if (item1.getId() == onlinePendingList.get(i).getId()) {
                            hasMatch = true;
                            onlinePendingList.remove(onlinePendingList.get(i));

                            //Compare Fields
                            if (!item1.getContent().equals(onlinePendingList.get(i).getContent())) {
                                itemChanged = true;
                            }
                            if (item1.getPriority() != onlinePendingList.get(i).getPriority()) {
                                itemChanged = true;
                            }
                            if (!item1.getDate_string().equals(onlinePendingList.get(i).getDate_string())) {
                                itemChanged = true;
                            }

                            if (itemChanged == true) {

                                //Format edit dates to date
                                DateFormat format = new SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH);
                                try {
                                    offlineDate = format.parse(item1.getDateAdded());
                                } catch (ParseException e) {
                                    e.printStackTrace();
                                }
                                try {
                                    onlineDate = format.parse(onlinePendingList.get(i).getDateAdded());
                                } catch (ParseException e) {
                                    e.printStackTrace();
                                }
                                //compare dates to see which was last edited
                                if (offlineDate.compareTo(onlineDate) > 0) {
                                    try {
                                        deleteRemoteItem(onlinePendingList.get(i), "item_delete");
                                        createNewRemoteItem(item1);
                                    } catch (JSONException e) {
                                        e.printStackTrace();
                                    }
                                } else if (offlineDate.compareTo(onlineDate) < 0) {
                                    addOrUpdateToDB(item1);
                                }
                            }
                        }
                        if (!hasMatch) {
                            deleteObjectFromDB(item1);
                        }
                    }
                }
            }
        }
        for (ToDoItem onlineItem1 : onlinePendingList) {
            boolean isManaged1 = onlineItem1.isManaged(); //returns false, which is ok since it is not yet in the realm db
        onlineItem1.setLocalId(counterObject.getCounter());
            addOrUpdateToDB(onlineItem1);
            boolean asdf = onlineItem1.isManaged(); //it returns false, but it should return true
            incrementCounter(counterObject);
        }
        initializeLists();
        getPendingListFragment().refreshFragment();

    }

 private void addOrUpdateToDB(ToDoItem newItem) {
        boolean test2= newItem.isManaged(); //returns false
        realm.beginTransaction();
        realm.copyToRealmOrUpdate(newItem);

        //realm.copyToRealm(newItem); //I tried this method as well, but no difference
        realm.commitTransaction();
        boolean test3= newItem.isManaged(); //returns false, and here is the problem, it should return true, shouldn't it?
    assignValuesToToDoItem(itemWithValues, newItem);
        saveCounterToDB(counterObject);
    }
    }

这里是GetItemsResponseClass的代码:

public class ToDoItem extends RealmObject implements Parcelable {
public static final Creator<ToDoItem> CREATOR = new Creator<ToDoItem>() {
    @Override
    public ToDoItem createFromParcel(Parcel in) {
        return new ToDoItem(in);
    }

    @Override
    public ToDoItem[] newArray(int size) {
        return new ToDoItem[size];
    }
};
@PrimaryKey
private long localId;
private String content;
private boolean checkedOffline = false;
private int priority;
private String date_string;
private String temp_id;
private long id;
private String date_added;


public ToDoItem(String name) {
    this.content = name;
}

public ToDoItem() {
}

protected ToDoItem(Parcel in) {

    localId = in.readLong();
    content = in.readString();
    checkedOffline = in.readByte() != 0;
    priority = in.readInt();
    date_string = in.readString();
    temp_id = in.readString();
    id = in.readLong();
    date_added=in.readString();
}

public int getPriority() {
    return priority;
}

public void setPriority(int priority) {
    this.priority = priority;
}

public boolean isCheckedOffline() {
    return checkedOffline;
}

public void setCheckedOffline(boolean checkedOffline) {
    this.checkedOffline = checkedOffline;
}

public Long getId() {
    return id;
}

public void setId(long id) {
    this.id = id;
}

public void setRemote_id(Long remote_id) {
    this.id = remote_id;
}

public String getContent() {
    return content;
}

public void setContent(String content) {
    this.content = content;
}

public boolean isDone() {
    return checkedOffline;
}

public String getDate_string() {
    return date_string;
}

public void setDate_string(String date_string) {
    this.date_string = date_string;
}

public long getLocalId() {
    return this.localId;
}

public void setLocalId(long i) {
    this.localId = i;
}

public String getTemp_id() {
    return temp_id;
}

public void setTemp_id(String temp_id) {
    this.temp_id = temp_id;
}

public String getDateAdded() {
    return date_added;
}

public void setDateAdded(String dateAdded) {
    this.date_added = dateAdded;
}


@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeLong(localId);
    dest.writeString(content);
    dest.writeByte((byte) (checkedOffline ? 1 : 0));
    dest.writeInt((priority));
    dest.writeString(date_string);
    dest.writeString(temp_id);
    dest.writeLong(id);
    dest.writeString(date_added);
}

@Override
public String toString() {
    return "localId: " + localId + "; content: " + content;
}
}

编辑:显然,对象不会使用其属性保存,这是一种理想的行为。因此,要分配值,您必须使用getter和setter。我添加了以下方法,但即使在使用手表进行调试时,如官方文档中所述,值也未分配:

public class GetItemsResponseClass extends JSONObject {


private String sync_token;

@SerializedName("temp_id_mapping")
private HashMap<String, Long> temp_id_mapping;

private boolean full_sync;

@SerializedName("items")
private ArrayList<ToDoItem> items;


public GetItemsResponseClass(){

}

public String getSync_token() {
    return sync_token;
}

public void setSync_token(String sync_token) {
    this.sync_token = sync_token;
}

public HashMap<String, Long> getTemp_id_mapping() {
    return temp_id_mapping;
}

public void setTemp_id_mapping(HashMap<String, Long> temp_id_mapping) {
    this.temp_id_mapping = temp_id_mapping;
}

public boolean isFull_sync() {
    return full_sync;
}

public void setFull_sync(boolean full_sync) {
    this.full_sync = full_sync;
}

public ArrayList<ToDoItem> getItems() {
    return items;
}

public void setItems(ArrayList<ToDoItem> items) {
    this.items = items;
}
}

我在方法private void assignValuesToToDoItem(ToDoItem itemWithValues, ToDoItem newItem) { realm.beginTransaction(); newItem.setContent(itemWithValues.getContent()); //the content variable stays null newItem.setCheckedOffline(itemWithValues.isDone()); //stays false newItem.setPriority(itemWithValues.getPriority()); newItem.setDate_string(itemWithValues.getDate_string()); newItem.setTemp_id(itemWithValues.getTemp_id()); newItem.setId(itemWithValues.getId()); newItem.setDate_added(itemWithValues.getDate_added()); realm.commitTransaction(); }

的主要活动中添加了这一行assignValuesToToDoItem(itemWithValues, newItem);

同样的结果......

2 个答案:

答案 0 :(得分:1)

我发现了两件非常重要的事情:

  1. 保存属性,但在调试窗口中,它们显示为0falsenull
  2. 即使放置调试监视器也不会显示正确的值。
  3. 要查看数据库中的实际值,您必须添加一个Watch并将手表直接放在对象的getter上。在我的情况下,我添加了一个Watch并输入“newItem.getContent()”。有了这条线,我得到了我的对象的标题。然而,只需将带有“newItem”的Watch显示为“null”。

答案 1 :(得分:0)

copyToRealm()copyToRealmOrUpdate() 返回 托管代理,作为您正在调用的函数的返回值

    realm.copyToRealmOrUpdate(newItem);
    realm.commitTransaction();
    boolean test3= newItem.isManaged(); //returns false, and it should return false

应该是

    newItem = realm.copyToRealmOrUpdate(newItem);
    realm.commitTransaction();
    boolean test3= newItem.isManaged(); //returns true