Tại sao viết tất cả những serializers tùy chỉnh khi bạn có thể làm Gson và Realm làm việc cùng nhau chỉ với một dòng mã?
TL; DR.
Bạn chỉ có thể giải quyết vấn đề này bằng cách chuyển không được quản lý RealmObjects
sang số Trang bị thêm cuộc gọi của bạn.
Nếu bạn không muốn xem hết câu trả lời này, hãy chuyển đến phần "Giải pháp được đề xuất" được đăng bên dưới.
dài talk (câu trả lời dài dòng)
này không có gì để làm với Retrofit. Nếu bạn đã đặt Gson làm công cụ chuyển đổi dữ liệu sang phiên bản Trang bị thêm hiện tại của mình, thì bạn có thể chắc chắn rằng đó là Gson những người không thành công.
Giả sử chúng ta có mẫu này:
public class Model extends RealmObject {
@PrimaryKey
long id;
boolean happy;
public Model() {/* Required by both Realm and Gson*/}
public Model(long id, boolean happy) {
this.id = id;
this.happy = happy;
}
public long getId() {
return id;
}
public boolean isHappy() {
return happy;
}
}
Đối với mã này, chúng tôi sẽ không có vấn đề:
Model unmanagedModel = new Model(5, true); // unmanagedModel
new Gson().toJson(unmanagedModel); // {id : 5, happy : true}
Nhưng đối với cái này:
Realm realm = /*...*/;
Model managedModel = realm.copyToRealm(unmanagedModel);
new Gson().toJson(managedModel); // {id : 0, happy : false}
// We'll get the samething for this code
Model anotherManagedModel = realm.where(Model.class).equalTo("id",5).findFirst();
new Gson().toJson(anotherManagedModel); // {id : 0, happy : false}
Chúng tôi sẽ ngạc nhiên. Chúng tôi đang xem nulls
ở khắp mọi nơi !.
Tại sao?
Gson thất bại serializing một RealmObject
chỉ nếu đó là một quản lý một.Điều này có nghĩa là hiện tại có một phiên bản Realm
mở được đảm bảo rằng RealmObject
này phản ánh những gì hiện đang được giữ trong lớp kiên trì (cơ sở dữ liệu Realm
).
Lý do tại sao điều này xảy ra là do bản chất mâu thuẫn như thế nào cả Gson và Realm làm việc. Trích dẫn Zhuinden về việc tại sao Gson thấy null
ở khắp mọi nơi:
... đó là bởi vì GSON cố gắng đọc các lĩnh vực của đối tượng Realm thông qua phản ánh, nhưng để có được những giá trị, bạn cần phải sử dụng phương pháp accessor - được tự động áp dụng cho tất cả các truy cập lĩnh vực trong mã qua Realm-biến áp, nhưng phản ánh vẫn thấy null ở khắp mọi nơi ...
Christian Melchior đề xuất một workaround t xung đột của anh ấy bằng cách viết một tuỳ chỉnh JsonSerializers
cho mọi ảnh được tạo Model
. Đây là giải pháp thay thế bạn đã sử dụng, nhưng Tôi KHÔNG khuyến nghị sử dụng nó. Như bạn đã nhận ra, nó yêu cầu viết nhiều mã là lỗi dễ bị và điều tồi tệ nhất, giết chết những gì Gson
là khoảng (điều này làm cho cuộc sống của chúng ta bớt đau).
giải pháp khuyến nghị
Nếu chúng ta bằng cách nào đó có thể đảm bảo realmObject
chúng tôi vượt qua để Gson không phải là một managed
một, chúng tôi sẽ tránh xung đột này.
Giải pháp 1
Nhận một bản sao trong bộ nhớ của RealmObject quản lý và vượt qua nó để Gson
new Gson().toJson(realm.copyFromRealm(managedModel));
Giải pháp 2
(Bao bì các giải pháp 1). Nếu giải pháp 1 là quá tiết cho bạn, làm cho mô hình của bạn trông như thế này:
public class Model extends RealmObject {
@PrimaryKey
long id;
boolean happy;
// Some methods ...
public Model toUnmanaged(Realm realm) {
return isManaged() ? realm.copyFromRealm(this) : this;
}
}
Và sau đó, bạn có thể làm một cái gì đó như thế này:
// You can pass null when you're sure your model is unmanged
new Gson().toJson(model.toUnmanaged(realm));
Giải pháp 3
Nếu (như tôi) bạn nghĩ rằng nó làm cho nó xấu xí để vượt qua nulls
hoặc để yêu cầu một Realm
khi làm một số serialization, sau đó bạn có thể đi với nhân bản mô hình của bạn. Không cần số Realm
!
Đã được đăng here (cuộn xuống và tìm bài đăng của @ AnixPasBesoin).
1 - Tạo một giao diện CloneableRealmObject generic:
interface CloneableRealmObject<T> {
T cloneRealmObject();
}
2 - Thực hiện realmObjetcs của bạn thực hiện các giao diện ở trên như sau:
public class Model extends RealmObject implements CloneableRealmObject<Model> {
@PrimaryKey
long id;
public Model() {
// Empty constructor required by Realm.
}
@Override
public Model cloneRealmObject() {
Model clone = new Model();
clone.id = this.id;
return clone;
}
}
3 - Clone đối tượng trước khi đi qua các cuộc gọi Retrofit của bạn.
new Gson().toJson(model.cloneRealmObject());
Trong một bài viết gần đây
Tôi đưa một answer giải thích lý do tại sao chúng tôi đang nhận được đầu ra tuần tự kỳ lạ này khi sử dụng managed
realmObjects
. Tôi khuyên bạn hãy xem nó.
Bonus
Bạn cũng có thể muốn kiểm tra RealmFieldNamesHelper, thư viện do Christian Melchior "để làm cho Realm truy vấn loại hơn an toàn".
Không rõ bạn đang gặp phải vấn đề gì? Rò rỉ bộ nhớ nào? –
Hwo bạn có nhận được 'response.body(). AnotherObject;'? Bạn nên sử dụng 'response.body(). Get (0 ..);'? –
Cảm ơn tất cả các bạn, bây giờ vấn đề đã biến mất, tôi chỉ cần thêm phân đoạn loại trừ vào tất cả cá thể gson của tôi. – cana