Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android component: RealmCursor #438

Closed
loosemoose opened this issue Oct 1, 2014 · 64 comments
Closed

Android component: RealmCursor #438

loosemoose opened this issue Oct 1, 2014 · 64 comments

Comments

@loosemoose
Copy link

Realm for Android looks awesome; however there are some Android specific use cases where certain elements work better when backed by a Cursor (http://developer.android.com/reference/android/database/Cursor.html) and when using a CursorLoader (http://developer.android.com/reference/android/content/CursorLoader.html). Is there any plans for supporting this interface?

@mmoussamob
Copy link

+1

@shbi
Copy link

shbi commented Oct 1, 2014

+1 would love to see support for this.

@cigoe
Copy link

cigoe commented Oct 1, 2014

+1

@c-lemire
Copy link

c-lemire commented Oct 1, 2014

+1 In my opinion, a Cursor interface implementation would vastly improve adoption of Realm as an Android DB replacement.

@emanuelez
Copy link
Contributor

Actually RealmResults already loads data lazily, just like a Cursor, so we're working on an Adapter to exploit this feature. But of course we're all ears for further improvements! :)

@bmunkholm
Copy link
Contributor

Could any of you please give us some concrete examples of where you think Realm could benefit from Cursor or CursorLoader support? We can easily support an AsyncTaskLoader. Wouldn't that be sufficient?

@c-lemire
Copy link

c-lemire commented Oct 8, 2014

Think catalog app. Copy part or all of a large catalog to the device to prevent having to fetch it again every time you need it. Then you want to display this catalog in its entirety in a large list, or significantly large queries from the catalog in a list.

Android provides easy methods for accomplishing this when the data is provided by the Cursor interface.
LoaderManager/CursorLoader, CursorAdapter, SimpleCursorAdapter, CursorTreeAdapter, etc.

And then lets say we want to expose that catalog to a partner app. Now we might need a ContentProvider to query, which should return a Cursor.

While we may be able to build a custom adapter set that takes advantage of Realm's lazy loading, not being able to use the standard tools, or extensions of the standard tools tends to be a lot of work in the long run.

To be universally useful (and a viable replacement for the native sqlite), we must be able to back the view of an arbitrarily large list without having to fully realize the backing data (all of the Adapter implementations), and be able to query in the background and load the results when they are ready (Loaders). Other utilities are useful as well, like joiners and mergers, but I consider those less significant because one can usually just run the query to produce the same set explicitly.

This is just an example, there are probably better ones, but this came to mind immediately. I'll also be the first to admit that I haven't given Realm a deep look yet, so I could easily have missed something critical during my quick overview.

@cmelchior
Copy link
Contributor

When working with Realm a CursorLoader could easily be replaced by ASyncTaskLoader. Where cursors really shine are when backing ListViews, ie. in CursorAdapters.

This is due to the fact that Cursors don't allocate any memory except for those data that are actually used, so they are really memory efficient, even more so than Realm as currently you will have to use an ArrayAdapter which will create an (very small) object when reading each item, which will result in GC's when scrolling through large lists fast.

On the other hand, a common pattern is using wrapper objects for cursors, something like:

    public Person getEntryFromCursor(Cursor c) {
        String name = c.getString(c.getColumnIndexOrThrow(Database.COLUMN_NAME));
        int age = c.getInt(c.getColumnIndexOrThrow(Database.COLUMN_AGE));
        return new Person(name, age);
    }

which is effectively the same as using a ArrayAdapter with RealmResults. So on those grounds you could probably argue against a RealmCursor implementation.

However by not providing a RealmCursor you really ignore a huge part of the current Android API's, the most prominent making it impossible to create a RealmContentProvider. It will also make it harder for people using their existing knowledge / tools for working with Cursors, which as @c-lemire points out, there are quite a lot of.

That was quite a ramble, but basically: Yes, Cursors have a horrible interface, but given the current state of the Android API's you cannot really ignore them.

@patrick91
Copy link

+1

I'd like to use Realm for a Content Provider

@bmunkholm
Copy link
Contributor

Hi Patrick,
Could you explain your usecase for the ContentProvider?

Thanks!

On Mon, Dec 1, 2014 at 11:00 PM, Patrick Arminio [email protected]
wrote:

+1

I'd like to use Realm for a Content Provider


Reply to this email directly or view it on GitHub
#438 (comment).

@patrick91
Copy link

Well, Content Provider are used mainly when you have to give access to your data to other apps.

But I see more and more developers using them inside their app (like I'm doing right now). Even if they are quite complex to set, they are a good abstraction from the underlining data structure.

Let's say I've a Content Provider (based on sqlite) I use all over my app, If I ever need to change from sqlite to realm I only have to change the Content Provider.

@renaudcerrato
Copy link

Cursors are definitely a needed feature. As melchior stated, we cannot ignore them. Only an iOS guy could, aren't you? ;)

Cursors allows to maintains a "window" on the dataset (thus allowing recycling). I dont want to feed my adapters with thousands of object (or even more) unlikely to be fetched again.

As about content providers: that's all about data sharing between applications!

@bmunkholm
Copy link
Contributor

So far, we have just only gotten the feedback that people stay as far away
from Content Providers as possible for various reasons. So it's obviously
interesting to hear that you experience the opposite :-)
I can surely understand the desire to abstract your database access (and be
independant of which db you use).
The issue is just that you will also limit yourself to that API,
featureset, and possible performance.
I guess we are trying to balance the innovation / new ways of doing things
versus the established standards.
For now we are surely not doing enough on supporting the established norms
:-)
At least for transtitions from "bad" to "better", even suppoting "bad" may
be an idea :-)

Thanks for sharing your needs!

On Tue, Dec 2, 2014 at 11:02 AM, Patrick Arminio [email protected]
wrote:

Well, Content Provider are used mainly when you have to give access to
your data to other apps.

But I see more and more developers using them inside their app (like I'm
doing right now). Even if they are quite complex to set, they are a good
abstraction from the underlining data structure.

Let's say I've a Content Provider (based on sqlite) I use all over my app,
If I ever need to change from sqlite to realm I only have to change the
Content Provider.


Reply to this email directly or view it on GitHub
#438 (comment).

@almozavr
Copy link

almozavr commented Dec 3, 2014

While realm has global db listener, I can't find a way to be notified only when particular result (or 'window') changes. E.g. you have a ProfileFragment and want to bind profile (1 RealmObject, or some JoinObject) data to ui and be refreshed automatically on data changes. Without Loader/ContentProvider I have to listen to all changes and refresh ui every time even if unrelated data changes? Sorry, if I miss something :(

@bmunkholm
Copy link
Contributor

You are right that at the moment we are missing more finegrained change
notifications - and we are working on that at the core database level.
Unitil that is available, you could create and send your own notification
at the point where you update your data.

On Wed, Dec 3, 2014 at 11:47 AM, Aleksey Malevaniy <[email protected]

wrote:

While realm has global db listener, I can't find a way to be notified only
when particular result (or 'window') changes. E.g. you have a
ProfileFragment and want to bind profile (1 RealmObject, or some
JoinObject) data to ui and be refreshed automatically on data changes.
Without Loader/ContentProvider I have to listen to all changes and refresh
ui every time even if unrelated data changes? Sorry, if I miss something :(


Reply to this email directly or view it on GitHub
#438 (comment).

@psh
Copy link

psh commented Dec 30, 2014

We have utilized content providers heavily in our application as the OS provided DataLoader has allowed us to avoid threading issues, hide a bunch of rest + database nastiness behind a clean (Cursor based) interface and utilize notifyDataSetChanged() for updates. We had a lot of luck extending AbstractCursor to walk around the (in memory) Pojo based data instead of it being database data.

I'd like to add my +1 to the request to make Realm work with content providers + cursors, and happy to talk at more depth/help out if you're interested.

@phu
Copy link

phu commented Jan 13, 2015

Another +1 here for ContentProvider support. I'd assumed this would be possible without really thinking carefully about it when I picked Realm for a project that needs to sync often with a server, the plan being to put all data access behind a single CP so any widget/view querying the data can do so the same way and receive updated data when necessary.

I'm not a fan of the way ContentProvider works, but it does, and as mentioned it's what a lot of people are used to (plus, in the same vein, there's plenty of doc and discussion out there for it).

For now I'll probably just go with a couple of custom adapters based on the example in the codebase, but it would definitely be nice (and, for more complex projects, perhaps necessary) to either provide a RealmContentProvider or facilitate reasonably painless creation of such a beast. A RealmCursor might be a good middle ground with perhaps more diverse potential applications.

@FunMiles
Copy link

FunMiles commented Feb 1, 2015

+1 for cursor and ContentProvider support.

@bangarharshit
Copy link

+1. Android provides minor things such as retained cursor in CursorLoader across configuration change. It is a big deal. Though this functionality can be achieved just by replacing cursors with RealmResults.

@sharathp
Copy link

+1

@cmelchior cmelchior added the P1 label Feb 19, 2015
@baolongnt
Copy link

+1 for cursor and ContentProvider support

@rpgobjects
Copy link

  • 1 for cursor support. if you want to use realm with a searchview your only options is to give it a cursoradapter.

@cmelchior cmelchior changed the title android.database.cursor interface support Android component: RealmCursor Apr 15, 2015
@impekable-james
Copy link

+1

Realm looks interesting, but it's exclusion of this feature chain preventing my use of Cursors have completely discounted it from an option in my toolkit. Cursor and the related ContentProviders allow for a broader scope of drop-in implementation and event notifications than Realm has presently exhibited in my testing. On a tablet, for example, I have one application that shows four parallel list views with different renders of some shared items, and allows dragging and dropping these items between some of the components [ (A) -> (B), (A) -> (C), (B, C) -> (D) ] but all objects are the same and feed from the same table, evolving through states and triggering implicit changes/actions on update. Using the native cursor loader I had to write almost zero logic for that action completed and updated all visible lists as well as a background network broadcaster which communicated the change to a subordinate network link for subscribed children as well. I can also easily register individual view elements to listen for a specific content URI record and update accordingly. Incidentally this also blocks the use of my library which exposes the ContentProvider as a direct network REST service which I sometimes use to inject data live into an application from a browser or another on-device application (self-contained server app style). All of these are features I have come to expect from Cursor and ContentProviders for more than a year, so losing these features to a reduced feature set is not an option. So far, this implementation seems quite bulky and cumbersome to implement in Realm without a lot more work to wrap and adapt the necessary components.

I was also surprised to see the use of private properties recommended in the model with generated virtual methods as that is not the recommended method for properties in Android (http://developer.android.com/training/articles/perf-tips.html#GettersSetters).

@cmelchior cmelchior mentioned this issue May 6, 2015
@cmelchior cmelchior self-assigned this May 6, 2015
@itrethan
Copy link

+1

@cmelchior cmelchior removed the P1 label May 20, 2015
@aercanozcan
Copy link

I agree with @Renascienza.
But I am also open to other solutions to share data between apps using Realm.(other than parcelable, Bundle,Intent because of 1mb data cap)

@cmelchior
Copy link
Contributor

We are working on process support as well: #1091
It will only work for apps where they both are using Realm. If that is acceptable, it will be transparent which app edited the data. It will just look like a background thread was doing it.

If you want to share data with arbitrary other apps there is no way around the ContentProvider/Cursor interface unfortunately.

@nishad358
Copy link

+1
Waiting for this feature. Will use Realm as soon as they add Cursor support.

@bmunkholm
Copy link
Contributor

Great to hear @nishad358. Could you also please elaborate your use case?

@nishad358
Copy link

Use case is same as what others have discussed. We use Content providers for syncing and as a layer between UI and data.

@cmelchior cmelchior removed their assignment Aug 29, 2015
@cmelchior cmelchior added P2 and removed P1 labels Aug 31, 2015
@petersnoopy
Copy link

+1

@guillermomuntaner
Copy link

+1 because cursor is the only way to support some basic default Android features like searchView.

@cmelchior Edited. Thank you for the clarification.

@cmelchior
Copy link
Contributor

@guillermomuntaner A RealmResults or RealmList have the same Java heap memory footprint as a Cursor because we they also lazy-load their data the same way a cursor does, and they have even better native memory footprints as we don't copy data to CursorWindows first.

We do still want to support cursors though, because as you point out, some Android API's only work on Cursors.

@zayo
Copy link

zayo commented Dec 30, 2015

+1

@badboyhb
Copy link

badboyhb commented Feb 4, 2016

Two suggestions:
1,Move "io.realm.internal.Row" and "io.realm.internal.Table" to package "io.realm".
2,Add method "public Row getRow()" to "RealmObject"

@badboyhb
Copy link

badboyhb commented Feb 4, 2016

Now I get the row for RealmObject by reflection.

Field f = RealmObject.class.getDeclaredField("row");
f.setAccessible(true);
Row r = (Row) r.get(RealmObject);
r.getLong(columnIndex1);
r.getString(columnIndex2);

@cmelchior
Copy link
Contributor

Hi @badboyhb
The Row and Table classes are not really intended to be public. If you want a more dynamic access to Realm data you can use our new Dynamic API which will give you methods like obj.getString() and `obj.getLong(): https://realm.io/docs/java/latest/#dynamic-realms

Regarding Cursors we have a PR here that adds it but there still is some corner cases we need to find solutions for: #1090

@nolsigan
Copy link

+1 for cursor

@cmelchior
Copy link
Contributor

We are splitting all Android specific components into their own repo. So this issue has been transferred to here: realm/realm-android-adapters#6

@droidahmed
Copy link

+1 for cursor and ContentProvider support

@Zhuinden
Copy link
Contributor

I wonder if it's possible to share managed objects between processes. O_o

@beeender
Copy link
Contributor

@Zhuinden 😶 it is actually possible ....

@Marchuck
Copy link

Marchuck commented Jan 8, 2017

+1 for cursor and ContentProvider support

@petersnoopy
Copy link

Any news?

@cmelchior
Copy link
Contributor

@petersnoopy This has pretty low priority at the moment, sorry. The issue is being tracked here now: realm/realm-android-adapters#6

@Zhuinden
Copy link
Contributor

@petersnoopy it's low prio because ContentProvider assumes multi-process safety.

But RealmResults<T> works like a cursor anyways, with lazy-load and reading a row you index only

@tieorange
Copy link

+1

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 16, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.