Why object replace instead update in Realm? - android

I am working on some chat - app whith complex messages.
Messages from API stored in realm DB.
When i getting messages: call after API response, deserialization finished, messages correct:
realm.beginTransaction();
realm.copyToRealmOrUpdate(listOfBaseMessageResponses);
realm.commitTransaction();
messages in db replaced and i forced to make a List in my activity and try to handle changes by myself.
Changes tracked in activity by:
messagesChangedListener = new RealmChangeListener() {
...
}
mBaseMessageResponsesRealm = realm.allObjects(BaseMessageResponse.class);
mBaseMessageResponsesRealm.addChangeListener(messagesChangedListener);
Way to get messages:
return realm.allObjects(BaseMessageResponse.class);
BaseMessageResponse class(getters and setters exists. for better understanding not show):
#SerializedName("clr")
#Expose
#PrimaryKey
private String clr;
#SerializedName("cap")
#Expose
private String cap;
#SerializedName("eoc")
#Expose
private int eoc;
#SerializedName("list")
#Expose
private RealmList<MessageInResponse> list = new RealmList<MessageInResponse>();
...
Also MessageInResponse contain nested classes.
Why messages replaced? I try many ways to figure it out but no result.
May be some problems with PK and logic for copyToRealmOrUpdate method?

Related

Realm avoid updating nested object

I have an app that stores lots of data to work offline as well.
I have three classes, in a hierarchy like;
public class MainGroup
{
private UUID Oid;
private String name;
private Date CreatedOn;
}
-
public class Group
{
private UUID Oid;
private String name;
private Date CreatedOn;
private MainGruop MainGroup;
}
-
public class Product
{
private UUID Oid;
private String name;
private Date CreatedOn;
private MainGruop MainGroup;
private Group Group;
}
( Oid fields are selected as PrimaryKey with realm attribute. )
Let's say, all MainGroup objects were stored in Realm DB. Then, when i'm trying to insert Group objects, with nested MainGroup object but with only its Oid field to link its master, Realm updates the MainProduct record (with given Oid), and clear the other fields as nulls.
In same way, when i'm inserting Product objects and nested objects are includes only Oid, realm updates all fields with nulls.
So, there are more complex and deeply related objects and when i make a request to get JSON from server, i must produce a very big JSON response to keep data.
And mention to insert method; I'm creating java objects with JSON response via GSON and i'm using Realm.copyToRealmOrUpdate(obj); method to insert.
To reduce payload (JSON size, serialize and insertion process), i need to find a way to fix this issue.

Realm Update Table Ignore Field

Following is Pojo are extended by realm , at first time getting all fields from api and i am using insertOrUpdate() operation of realm to dump data in realm.
ServiceModel.java
#JsonProperty("id")
private String id;
#JsonProperty("title")
private String title;
#JsonProperty("description")
private String description;
#JsonProperty("current_status")
private String currentStatus;
But for next time i am not getting current_status field from response and so my ServiceModel table is getting updated with currentStatus as null. How To make currentStatus to not getting updated if it is not in response.
I had the same problem and here how I solved it. You should select existing Object by id:
ServiceModel existingService = realm.where(ServiceModel.class).equalsTo("id",id).findFirst();
if(existingService !=null){ // check if such record existed, it may be absent
String oldCurrentStatus = existingService.currentStatus();
//set old current status to new API object
}
I had the same problem and as far as I know there is no Realm function or annotation yet for such case.

Realm: How to import 5 Millions objects without crashing

I have to migrate a 5 million tuples sqlite database to realm. The database will be for consultation only. I started converting the 5M tuples from sqlite to json and importing the data with createAllFromJson (). It was taking too long, so I decided to use FlatBuffer instead of json and do the import manually. The problem is that after several import iterations it returns the following exception: io.realm.exceptions.RealmError: Unrecoverable error. Mmap () failed: Out of memory size.
I learned that closing realm is really important for this kind of issues. So I end up building and closing a realm every time I iterate, but I still get that issue.
Doing some research I learned that realm passes really badly with long files. I assume that I have to split the file into several an query them separately.
My question is this:
How do I separate a large realm file into different small files, query them and keep the incredibly fast response?
Is splitting the right aproach?
I have only 1 RealmModel:
public class Owner extends RealmObject {
#PrimaryKey
private long id;
#Index
private String name;
#Index
private String mix;
#Index
private String entry;
#Index
private String value;
// ... Generated getters and setters ...
}
And I insert this way:
for (int i=0; i<flat_buffer_list.lenght(); i++){
RealmConfiguration config = new RealmConfiguration.Builder()
.name("owner.realm")
.build();
Realm realm=Realm.getInstance(config);
OwnerList list= flatbuffer.OwnerList.getElementAsRoot(flat_buffer_list.get(i));
for (int i=0; i<list.lenght(); i++){
//create the realm object an perform a realm.insert(object)
}
realm.close();
}

Realm Android - How can I convert RealmResults to array of objects?

I have an object
public class ArticleList extends RealmObject {
#PrimaryKey
private String id;
private String title;
private String subtitle;
private String image;
private String category;
}
What I want to do is to fetch result from Realm and them convert result to ArticleList[]
Fetch I do by using
RealmResults<ArticleList> results = realm.where(ArticleList.class).equalTo("category", "CategoryName").findAll();
What do I have to do next to get an array of objects ?
Simplest to convert into java ArrayList:
ArrayList<People> list = new ArrayList(mRealm.where(People.class).findAll());
List<ArticleList> unmanagedList = realm.copyFromRealm(results);
Will do it.
RealmResults has a toArray() method - also toArray(T[] contents) (note the RealmResults inheritance chain). You can use these as follows:
ArticleList[] resultArray = (ArticleList[]) results.toArray();
Or
ArticleList[] resultArray = results.toArray(new ArticleList[results.size()]);
Ideally, you'd want to use RealmResults instead. This allows you to get "free" updates to your data, as well as all the conveniences of a List.
Instead of trying to convert to an array, you should extend the abstract RealmBaseAdapter class from https://github.com/realm/realm-android-adapters to keep your results in sync.
Realm provides these classes as an example of how to create an auto-updating list with a RecyclerView or a ListView.

Sugar ORM is not saving data into the database

I am currently using Sugar ORM and Android Async Http Client for my Android application.
I read through the documentation of Sugar ORM and did exactly what is written there.
My HttpClient is using the singleton pattern and provides methods for calling some APIs.
Now comes the bad part about it. I am not able to save the data persistently into my database which is created by Sugar ORM.
Here is the method, that is calling an API:
public void getAvailableMarkets(final Context context, final MarketAdapter adapter) {
String url = BASE_URL.concat("/markets.json");
client.addHeader("Content-Type", "application/json");
client.addHeader("Accept", "application/json");
client.get(context, url, null, new JsonHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, JSONArray response) {
Log.i(TAG, "Fetched available markets from server: " + response.toString());
Result<Markets> productResult = new Result<Markets>();
productResult.setResults(new Gson().<ArrayList<Markets>>fromJson(response.toString(),
new TypeToken<ArrayList<Markets>>() {
}.getType()));
ArrayList<Markets> marketsArrayList = productResult.getResults();
// This lines tells me that there are no entries in the database
List<Markets> marketsInDb = Markets.listAll(Markets.class);
if(marketsInDb.size() < marketsArrayList.size() ||
marketsInDb.size() > marketsArrayList.size()) {
Markets.deleteAll(Markets.class);
for(Markets m : marketsArrayList) {
Markets market = new Markets(m.getId(), m.getName(), m.getChainId(), m.getLat(),
m.getLng(), m.getBusinessHourId(), m.getCountry(), m.getZip(), m.getCity(),
m.getStreet(), m.getPhoto(), m.getIcon(), m.getUrl());
market.save();
adapter.add(market);
}
adapter.notifyDataSetChanged();
}
List<Markets> market = Markets.listAll(Markets.class);
// This lines proves that Sugar ORM is not saving the entries
Log.i(TAG, "The market database list has the size of:" + market.size());
}
});
}
This is what Logcat is printing:
D/Sugar: Fetching properties
I/Sugar: Markets saved : 3
I/Sugar: Markets saved : 5
I/RestClient: The market database list has the size of:0
Also I took a look at the Sugar ORM tag here at stackoverflow, but no answers or questions could give me a hint on how to solve that problem.
I am a newbie to the android ecosystem and would love any help of you guys to solve this problem.
Thanks in advance
I just solve it the same problem as you have.
It was a pain in the neck but after few hours I find out what caused this problem.
Using Sugar ORM you must not set id property as it's belongs to SugarRecord class,
otherwise ORM will try to update objects instead of insert them.
As I need to have field with my object id, I used json annotation to assign it to another field.
Last step was configure GSON to exclude fields without Expose annotation.
So my class looks like one below now:
public class MyClass
{
#Expose
#SerializedName("id")
private long myId;
#Expose
private String field1;
#Expose
private String field2;
#Expose
private byte[] field3;
#Expose
private double field4;
public MyClass() { }
// parametrized constructor and more logic
}
Cheers!

Categories

Resources