Android Realm: Retrieve collection ids from realm Object - android

I have saved my User to the realm. When I query the user I get this object:
User{id=0, hairColor=Red, favoriteSongs=FavoriteSong#[16,17]}
When I want the list of favorite songs, realm makes it easy to get a list back:
mUser.getFavoriteSongs();
But I'd like to get an array of the user's favoriteSong ids. This will make it easy to pass in a bundle as an int[].
Is this possible in Realm?

I would propose you two options:
Create a helper responsible of iterate the list of Songs and return a list of ids.
class SongHelper {
public static List<Integer> getSongIds(List<Song> songs) {
List<Integer> songIds = new ArrayList<>();
for( Song song : songs )
songIds.add( song.getId() );
return songIds;
}
}
Override the getFavoriteSongs method and make it return List<Integer> instead of List<Song> or create an additional method for this in the User.
Option 1 is more elegant. You should always keep your model classes as clean as possible. In other words, just declare attributes, getter and setters without business logic.

Related

Remove duplication from an array of objects

I have an object like below,
class LocationData{
String time;
String name;
String address;
}
for this object i have created getter setter.
By using service i fill this above model and save into room database.
whenever user open my app i just update the room database data to server using API.
Now sometimes the time duplication occurred. How to remove the object from array based on time. time should be unique.
You can use the extension function distinctBy. If you have an array of LocationData objects called allLocations it would be
val distinctLocations = allLocations.distinctBy { it.time }
Note distinctLocations will be a List; if you want it to be an array, use toTypedArray()

Realm DB how to get query output object as unmanaged?

I am trying to query my Realm DB such that the output will give an unmanaged object and for that, I changed my RealmList type of object to List.
Now the thing is in addchangeListener I am getting my output object(stories) value as managed. But the type of stories is List. So why my stories object is becoming managed where it should act as an unmanaged object.
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;
}
}
I am saying my List is managed because when i am trying to write below code I am getting 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`.
List<story> stories = realm.where(story.class).findAllAsync();
Because specifying the type List<story> just means you'll see the returned list as a List<story>, but technically it's still a RealmResults<story>.
stories.addChangeListener(new RealmChangeListener<RealmResults<story>>() {
This line underneath shouldn't even compile.
Stories should be stored in a field.
private RealmResults<story> stories;
public void ...() {
stories = ...
stories.addChangeListener(...
Anyways, so you are working with RealmResults, which means that in
class StoriesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
List<story> storyList;
This storyList you provided is a RealmResults<story>, so calling storyList.get(...) will return managed RealmObjects.
Managed RealmObjects are "temporarily immutable", meaning they can only be modified in a transaction. It is also generally not recommended to run write transactions on the UI thread.
The simplest way would be to use realm-android-adapters.
class StoriesAdapter extends RealmRecyclerViewAdapter<story, RecyclerView.ViewHolder> {
StoriesAdapter(OrderedRealmCollection<story> stories) {
super(stories, true, true);
}
}
And when you want to modify an object, you do
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");
}
});
And then Realm will handle automatically updating the RealmResults, the story object, and the RecyclerView.
EDIT: If you intend to use unmanaged objects, then you could use realm.copyFromRealm(results), except that does the read on the UI thread.
You could create a background looper thread and obtain the results from there, but managing that could be tricky. Luckily for you, there's a library I made called Monarchy which lets you do exactly that.
See the relevant sample code for how you'd use it.
The stories is implicitly Managed, the reason is that RealmResults extends the list interface abstractly. Thats why the casting is possible, underneath the same mechanisms for a RealmResults still takes precedence. Also, you should only pass RealmResults instance to an Adapter directly, if you register a RealmChangeListener on it, which will call adapter.notifyDataSetChanged(). Otherwise, writes will update the RealmResults content, and your adapter will be desynchronized.
Realm is not like SQLite or Core Data. If you’re using Realm, take advantage of live objects. Don’t implement any refreshing logic or requerying. Always allow the current class to own its own instance of a realm query.
This fact is true,Realm objects and any child objects are NOT thread-safe. They’re confined to a single thread to ensure that atomic rights are maintained. There is an internal list where every single thread has its own unique Realm instance. If you want to pass objects between a thread–for example, if you create a dog object on the main thread, pass it to the background thread, and then try and access a property–it will trigger an exception straight away.
Also you are using asynchronous query, which puts it on a worker thread.

How to find index in ArrayList<Class> (Android)

I use eclipse android
I need to index or object find in ArrayList
public class myclass
{
int id;
int count;
String value;
}
mainactivity
{
ArrayList<myclass> list = new ArrayList<myclass>();
myclass mc = new myclass();
mc.id=1;
mc.count=20;
mc.value="my value 1"
list.add(mc);
//add 100 record in list
//how can i this
int index = list.find(value="search value");
//or this
myclass founded = list.find(value="search value");
//or this
myclass founded2 = list.where(a => a.value="search value").first; //yes this is linq and lambda, but i cant linq in android
}
if I use for loop, I can find index but maybe arraylist has 1billion over record and I search 1000 values in arraylist
I dont want to use 1000 times for-loop in arraylist.
how can I this basicly
You can use indexOf()
int index = list.indexOf(object)
So if you want to find 1000 values inside your 1billion ArrayList record it is better not to use ArrayList here.
More preferable way for doing that is using HashMap<String, YourClass>.
Where first parameter is your id and second is element of your class.
You can easily found then element of your class by id. Approximately O(1).
If it is no matter how your values will be stored in ArrayList you can implements comparable interface in your class and support your collection in sorted way. So if your collection is sorted you can find your element with binary search.
You should use this version of binary search
Collections.binarySearch(List<? extends T> list, T object, Comparator<? super T> comparator)
So you can implement you custom compator to check if your object is equal to something that you are finding.

How do I store multiple values in an array in Android?

For this example I have an array:
String[] books = new String[x];
I would like to store the id and title in each location:
books[0]=>id:0, title:"book title1"
books[0]=>id:1, title:"book title2"
books[0]=>id:2, title:"book title3"
books[0]=>id:3, title:"book title4"
I want to store the id since it may change. I'm getting the id and title from a database. Getting the info isn't the issue. I want to store it this way so in my other functions this returns to I can use something like:
btn.setText(regions[i].title)
Any suggestion on how to handle this would be great.
Do one thing, first create a bean class like BookBean.
Under this declare two variables ID and Title. and declare getters and setters (If u are using eclipse u can easily do this by (Source -> generate getters and setters.. option)
and then declare a ArrayList to store BookBean vale as of follow.
ArrayList<BookBean> bookArrayList=new ArrayList<BookBean>();
for(int i=0;i<=urSize;i++)
{
// create a object for BookBean
BookBean book =new BookBean();
book.setID("what ever");
book.setTitle("what ever");
bookArrayList.ass(book)
}
It is better to use Arraylist with custom class.
see this
class Book
{
String id,title;
/* Cunstructor to store data */
public Book(String id,String title)
{
this.id = id;
this.title = title;
}
}
//declare arraylist
ArrayList<Book> bookList = new ArrayList<Book>();
bookList.add("1","book1");
bookList.add("2","book2");
bookList.add("3","book3");
bookList.add("4","book4");
btn.setText(bookList.get(i).title)
I think you have several options
Use a HashMap where you can use your id as key and value title
Define a class and keep id and title as attributes , define get and set methods.
Keep the objects of the class in a ArrayList

Adding items to Array List with specified objects

I am working in a translator kind of app and i need some help.
I have a class with getters and setters for my Array List objects. Each object has a phrase, a meaning, and usage.
so i have this to create my list:
ArrayList<PhraseCollection> IdiomsList = new ArrayList<PhraseCollection>();
now how do i add these objects to the list, each object containing the phrase, its meaning, and a use in a sentence?
For Example: The Layout would be something like this
Phrase
Kick the bucket
Meaning
When someone dies
Usage
My grandfather kicked the bucket
Thanks a lot
this is what i came up with that worked for me
private void loadIdioms() {
//creating new items in the list
Idiom i1 = new Idiom();
i1.setPhrase("Kick the bucket");
i1.setMeaning("When someone dies");
i1.setUsage("My old dog kicked the bucket");
idiomsList.add(i1);
}
ArrayList has a method call add() or add(ELEMENT,INDEX);
In order to add your objects you must first create them
PhraseCollection collection=new PhraseCollection();
then create the ArrayList by
ArrayList<PhraseCollection> list=new ArrayList<PhraseCollection>();
add them by :
list.add(collection);
Last if you want to render that in your ListView item, you must override the toString() in your PhraseCollection.
I suppose you would use the add(E) method (http://docs.oracle.com/javase/6/docs/api/java/util/ArrayList.html#add(E)).
Here is an example using your example provided.
public class Phrase {
public final String phrase, meaning, usage;
//TODO: implement getters?
public Phrase(String phrase, meaning, usage) {
this.phrase = phrase;
this.meaning = meaning;
this.usage = usage;
}
}
and use it like this:
// create the list
ArrayList<Phrase> idiomsList = new ArrayList<Phrase>();
// create the phrase to add
Phrase kick = new Phrase("kick the bucket", "When someone dies", "My grandfather kicked the bucket");
// add the phrase to the list
idiomsList.add(kick);

Categories

Resources