2

i am having a template / generics question.

This is the code i have at the moment

data class RealmWatcher<T>(
        val results: RealmResults<T>,
        val handler: (RealmResults<T>) -> Unit)

And and using this in an Android fragment to listen to specific results and execute actions based on the changes. So lets take this as an example

private val realmListener = arrayOf(
            RealmWatcher<Notification>(Realm.getDefaultInstance().where(Notification::class.java).equalTo("isNew", true).findAll(),
                                       { n: RealmResults<Notification> ->
                                           // DO STUFF
                                       })

I am doing this while start / stop of the fragment

override fun onResume() {
    super.onResume()
    // start listening and execute
    realmListener.forEach { it.handler(it.results) }
    realmListener.forEach { it.results.addChangeListener(it.handler) }
}

override fun onPause() {
    // stop listening
    realmListener.forEach { it.results.removeChangeListener(it.handler) }
    super.onPause()
}

It works only when i am using one type (like Notification above). How should I define that if i want to use different types in the form of

private val realmListener = arrayOf(
            RealmWatcher<Notification>(Realm.getDefaultInstance().where(Notification::class.java).equalTo("isNew", true).findAll(),
                                       { n: RealmResults<Notification> ->
                                       // TODO STUFF
                                       }),
            RealmWatcher<Project>(Realm.getDefaultInstance().where(Project::class.java).equalTo("isOdd", true).findAll(),
                                       { n: RealmResults<Project> ->
                                         // TODO STUFF
                                       })
                                       )

When mixing the types (Notification and Project) I will get a Type mismatch error.

And when defining the

private val realmListener:Array<RealmWatcher<out Any>>

I will also get Type mismatch errors

How can I define the Array to have several different RealmWatcher with different types T?

3
  • Hm, can you post the actual errors and where they occur? Commented Nov 16, 2017 at 16:34
  • Put variance on your realm watcher class i.e. data class RealmWatcher<out T> Commented Nov 16, 2017 at 23:17
  • @SimY4 That won't work, as T is also used in in position in the code. See my answer for a working solution that also encapsulates the logic better. Commented Nov 20, 2017 at 8:11

1 Answer 1

2

Doing exactly what you want is going to be tricky, because I don't know of a way to tell the compiler that what you're doing is actually safe. Adding variance, like one of the comments suggests, won't work as T is used in both in and out positions.

However, you could take a different approach. Extend your RealmWatcher like this:

data class RealmWatcher<T>(
    val results: RealmResults<T>,
    val handler: (RealmResults<T>) -> Unit
) {
    fun attach() {
        handler(results)
        results.addChangeListener(handler)
    }
    fun detach() {
        results.removeChangeListener(handler)
    }
}

and then use those two additional functions in your lifecycle callbacks:

fun onResume() {
    super.onResume()
    // start listening and execute
    realmListener.forEach { it.attach() }
}

fun onPause() {
    // stop listening
    realmListener.forEach { it.detach() }
    super.onPause()
}

This will do what you need it to do without creating a problem because of the mixed generic parameters.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.