vicpinm / Kotlin-Realm-Extensions

Kotlin extensions to simplify Realm API.
Apache License 2.0
535 stars 53 forks source link

Param Query<T> ignored #48

Closed cbedoy closed 6 years ago

cbedoy commented 6 years ago

I'm using Realm Extensions but currently no all our code is on Kotlin we have several layers that will need to refactor (Java), I know extensions are not supported on java, that why I created like and Grapper on kotlin that recieve RealmQuery instead of Query

I'd like to know (if you know). How I can made the compatibility between Query injected from a java class as RealmQuery.

I'm already know that you defined as

public typealias Query<T>  = io.realm.RealmQuery<T>.() -> kotlin.Unit

Where I supposed if you inject a field as RealmQuery should be supported, but seems like you library ignore my RealmQuery injected cuz isn't a Query

There's my example wrapper created in Kotlin it receive a class, fieldName, order and _query

    override fun <T : RealmObject> querySortedObjects(_clazz: Class<T>, _fieldName: String, _order: Sort, _query: RealmQuery<T>): List<T> {
        val newInstance = _clazz.newInstance()
        val results = newInstance.querySorted(_fieldName, _order, {
            _query
        })

        Timber.d("$javaClass -> querySortedObjects: ${_clazz.javaClass} results: ${results.size}")

        return results
    }

   override  fun <T : RealmObject> queryByClass(_clazz: Class<T>): RealmQuery<T>? {
        return try {
            Realm.getDefaultInstance().where(_clazz)
        }catch (e : Exception){
            null
        }
    }

And there's my code provide from java.

    @Override
    public List<User> getFavorites(@NotNull String query) {

        RealmQuery<User> userRealmQuery = mRealmProvider.queryByClass(User.class);

        if (userRealmQuery != null){

            userRealmQuery.equalTo("favorite", true);

            if (query.length() > 0)
                userRealmQuery.and().contains("name", query, Case.INSENSITIVE);

            userRealmQuery.isNotNull("name");

            return mRealmProvider.querySortedObjects(User.class, "name", Sort.ASCENDING, userRealmQuery);
        }
        return new ArrayList<>();
    }

Seems ignore my RealmQuery param

screen shot 2018-02-15 at 1 46 59 pm

Then seems just perform this


val results = newInstance.querySorted(_fieldName, _order)
vicpinm commented 6 years ago

Hi @cbedoy, you can call extensions functions from java without problems. Have you tried something like this?

List<User> result =  RealmExtensionsKt.querySorted(new User(), "id", Sort.ASCENDING, new 
Function1<RealmQuery<User>, Unit>() {
        @Override
        public Unit invoke(RealmQuery<User> query) {
            query.equalTo("field", "value");
            return Unit.INSTANCE;
        }
    });

And you can simplify this code if you use retrolambda.

cbedoy commented 6 years ago

Great! that works but my question is why seems my RealmQuery<<>> is ignored

override fun <T : RealmObject> querySortedObjects(_clazz: Class<T>, _fieldName: String, _order: Sort, _query: RealmQuery<T>): List<T> {
        val results = _clazz.newInstance().querySorted(_fieldName, _order, { 
            _query //this is ignored "The expression is unused"
        })
        return results
    }
vicpinm commented 6 years ago

@cbedoy You are trying to return an object inside the lambda. Lambda expression is defined as io.realm.RealmQuery.() -> kotlin.Unit. As you can see, it returns Unit, so you can't return a query object.