I have RealmResults that I receive from Realm like
RealmResults<StepEntry> stepEntryResults = realm.where(StepEntry.class).findAll();
Now I want convert RealmResults<StepEntry> to ArrayList<StepEntry>
I have try
ArrayList<StepEntry> stepEntryArray = new ArrayList<StepEntry>(stepEntryResults));
but the item in my ArrayList is not my StepEntry object, it is StepEntryRealmProxy
How can I convert it?
Any help or suggestion would be great appreciated.
To eagerly read every element from the Realm (and therefore make all elements in the list become unmanaged, you can do):
List<StepEntry> arrayListOfUnmanagedObjects = realm.copyFromRealm(realmResults);
But you generally have absolutely no reason to do that unless you want to serialize the objects with GSON (specifically, because it reads field data with reflection rather than with getters), because Realm was designed in such a way that the list exposes a change listener, allowing you to keep your UI up to date just by observing changes made to the database.
The answer by #EpicPandaForce works well. I tried this way to optimize my app performance and I find the following is a bit faster. Another option for people who prefer speed:
RealmResults<Tag> childList = realm.where(Tag.class).equalTo("parentID", id).findAll();
Tag[] childs = new Tag[childList.size()];
childList.toArray(childs);
return Arrays.asList(childs);
In Kotlin:
var list : List<Student>: listof()
val rl = realm.where(Student::class.java).findAll()
// subList return all data contain on RealmResults
list = rl.subList(0,rl.size)
Related
I have an initial list of elements in common
val commonList = mutableListOf<String>
I have the following object
ClassObject(val title: String, val subjects: List<String>)
Assuming you have such a list with initial data
val list = listOf<ClassObject> /* With a size of 1000 samples */
How can I iterate the initial list "list" and look in the list of "subjects" for the elements that are not in "commonList" and add them to this last list.
I had thought of a nested for loop, but it would require a lot of power and time.
list.forEach { c ->
c.subjects.forEach { s ->
if (s !in commonList)
commonList.add(s)
}
}
You should use MutableSet instead of MutableList for this purpose. Using an in check on a Set does not require iteration so it is far more performant. It would also make your code a lot simpler, because it won't redundantly add items, so you can simply use an addAll call on it to achieve the same thing as if you had first checked if each item is in the set first.
val commonSet = mutableSetOf<String>()
val list = listOf<ClassObject>( /*...*/ )
for (classObject in list) {
commonSet.addAll(classObject.subjects)
}
In Big-O notation, the above is O(n), whereas your original code is O(n^2).
So to paraphrase, it seems you want to accumulate all unique entries from your nested list into a flat list commonList.
In which case, using a MutableSet would be a good idea. I'm not familiar with the Kotlin implementation of sets, but traditionally they are like hashmaps that don't map keys to values but instead hold unique keys. The difference from a simple List being that they are internally more sophisticated than a plain array, and benefit from faster collision look-ups.
In conclusion, you can't really avoid the nested loop, but you can eliminate the wasteful !in check. If you must end up with a list at the end, you can always call toList on the set.
I wanna duplicate realm object and then change the second, without reassigning all the keys. How can I do this? RealmObject does not have .copy() or .clone() methods.
// Money is not data class and has ∞ fields which will be boring to re-assign
val money = Money()
money.amount = 1000
...
val anotherMoney = money
anotherMoney.amount = 500
println(money.amount) // prints 500
can you please provide more context and appropriate information as I do not see and array's in your code statement. Thank you.
EDIT
Because Money is not a data class, you do not have the auto-generated copy() function available, that leaves you with two options:
Create an custom copy() function in the Money class. This could be mundane if there are huge amount of fields in the class.
Use 3rd party libraries, in which case you'll add external dependency to your RealmObject.
What I will suggest is a no brainer: Try to convert your Money.class to a Data class. You will get auto generated functions and idiomatically it will work as RealmObjects should be key-values pairs.
EDIT
You can use GSON library's serialization/deserialization and hack your way to solve your problem (although this is a hacky way but will do its job):
fun clone(): Money {
val stringMoney = Gson().toJson(this, Money::class.java)
return Gson().fromJson<Money>(stringMoney, Money::class.java)
}
usage:
val originalMoney = Money()
val moneyClone = originalMoney.clone()
Let's say we have the stock of items stored in the JSON txt file. To access the data we load JSON file using a stringBuilder class, then populate StokItems into:
List<StockItem> stock;
like this:
stock.clear();
Gson gson = new Gson();
stock = gson.fromJson(stringBuilder.toString(), new TypeToken<List<StockItem>>() {
}.getType());
as we would like to take advantage of the LiveData in Android we introduced:
MutableLiveData<List<StockItem>> stockLiveData = new MutableLiveData<>();
To make it working we have to post data into it:
public LiveData<List<StockItem>> getLiveStockList() {
stockLiveData.postValue(stock);
return stockLiveData;
}
So here is the question, if the line:
stockLiveData.postValue(stock);
consumes memory for creating another copy of
List<StockItem> stock
and if so, could be it's a good idea to keep "original data" inside the
stockLiveData
variable only to reduce the memory impact? (If is it possible ...)
No need to use global variable to hold temporary data. either you can use local variable or directly post to LiveData.
public LiveData<List<StockItem>> getLiveStockList() {
return stockLiveData;
}
And then either
List stock = gson.fromJson(stringBuilder.toString(), new TypeToken<List<StockItem>>() { }.getType());
stockLiveData.postValue(stock);
or
stockLiveData.postValue(gson.fromJson(stringBuilder.toString(), new TypeToken<List<StockItem>>() { }.getType()))
You can also access the list inside LiveData like below:
stockLiveData.getValue();
Which return the original list data.
There are couple of things about your code I want to point out here:
You do not necessarily need to call postValue in your getter function. As far as there are observers observing from your getter function, you can post value from anywhere.
Even if you use mutable live data that does not necessarily mean that you're allocating memory for or creating a copy of List. When you set or post value on your Mutable Live Data, you're basically referencing the existing list on to value in your Mutable Live Data.
I have a recyclerview which shows a list of students.
All of the students are held in a realmlist in the adapter.
When the user can ask for a data refresh, than the server sends the list of students back to the user.
What i am doing now is to download all of the information from the server , store it in the db , than retrieving it from the database(via realmresults) and than converting the realmresult to realmlist.
My question is how to properly update the UI?
I have seen in the documentation that realmlist have a managed mode where they are updating the ui automatically..
What is this managed mode? What does it means?
How do i use the realmlist to keep it in a managed state?
And what is the right way(aka best practice) to use realmlists?
Note that i cannot hold my information as realmresult directly because im performing some manipulation on the data that i dont want it to be saved.
Managed Object vs. Standalone
The standalone RealmObject/RealmList is created through the Object's constructor or the Realm.copyFromRealm() method. The data accessing in the standalone object won't go through the underline storage engine, instead, it behaves just like normal object. So the standalone object won't be refreshed when data changes. Examples for standalone object:
MyModel myModel = new MyModel(); // Standalone
MyModel model = realm.where(MyModel.class).findFirst(); // This is managed object.
MyModel standaloneModel = realm.copyFromRealm(model); // The returned value is standalone object.
MyList myList = new MyList(); // Standalone
The managed RealmObject/RealmList are accessing data though Realm's underlying storage engine. They are created when you do query from Realm, or the return from the copyToRealm() (and its variant methods). Like:
MyModel model = realm.where(MyModel.class).findFirst();
MyModel model = new MyModel(); // This is a standalone object.
model = realm.copyToRealm(modle); // The returned value is managed by Realm now.
MyList myList = realm.where(MyModel.class).findFirst().getMyList();
How to properly update the UI
The suggestion is using Realm's change listeners. See https://realm.io/docs/java/latest/#notifications
And what is the right way(aka best practice) to use RealmList?
This is a bit confusing, but Realm is introducing RealmCollection into the next major release (v0.89.0). See https://github.com/realm/realm-java/pull/2345.
Note that i cannot hold my information as realmresult directly because im performing some manipulation on the data that i dont want it to be saved.
If the RealmList is in managed mode, the data changes will be saved as well. If you don't want some data to be saved, you could consider to use #Ignore annotation on those fields. See https://realm.io/docs/java/latest/#ignoring-properties
Update on 04072016
RealmList vs. RealmResults:
RealmList is a list of RealmObject saved as a field of a RealmObject. It represents the one-to-many relationship in Realm.
RealmResults is the results of query.
Both of them (if RealmList in managed-mode) will be auto-refreshed when data changes.
You can get a RealmResults from a RealmList by RealmList.where() like:
RealmResults results = myRealmList.where().findAll();
This answer will be a bit out-of-date after Realm v0.89.0 released, because of new RealmCollection.
I am new to android realm.
I am using follwing code to get product object from realm.
ProductModel prodObj = realm.where(ProductModel.class).equalTo("product_id","12").findFirst();
How can i create standalone copy of prodObj?
I want to update some field's value that should not affect in realm database. I don't want to set it manually with setters method because model class contains too many fields. Is there any easy way to create standalone copy of prodObj?
Since 0.87.0
Added Realm.copyFromRealm() for creating detached copies of Realm objects (#931).
Realm only has a copyToRealm method and not a copyFromRealm method. Currently, there is a number of restriction to model classes (see https://realm.io/docs/java/latest/#objects) but we are investigating and experimenting how to lift these.
We have an open issue about exactly what you are asking: https://github.com/realm/realm-java/issues/931. But for the time being, you will have to copy our objects manually.
In case anyone wondered like me how we can implement this copyFromRealm(), this is how it works:
ProductModel prodObj = realm.where(ProductModel.class)
.equalTo("product_id", "12")
.findFirst();
ProductModel prodObjCopy = realm.copyFromRealm(prodObj);
You can serialize an object into a JSON string and deserialize into a standalone object by Jackson like:
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(yourObject);
objectMapper.readValue(json, YourModel.class);
GSON might not work because it doesn't support getter/setter when it makes a JSON.
I know it's a horrible solution.
But it might be the only way yet.