Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

Custom Parcelers #40

Closed
gnawf opened this issue Dec 13, 2021 · 5 comments
Closed

Custom Parcelers #40

gnawf opened this issue Dec 13, 2021 · 5 comments

Comments

@gnawf
Copy link

gnawf commented Dec 13, 2021

I have an abstract class that I want to write a custom Parceler for per https://developer.android.com/kotlin/parcelize

e.g.

@Parcelize
data class User(val firstName: String, val lastName: String, val age: Int) : Parcelable {
    private companion object : Parceler<User> {
        override fun User.write(parcel: Parcel, flags: Int) {
            // Custom write implementation
        }

        override fun create(parcel: Parcel): User {
            // Custom read implementation
        }
    }
}

Cheers.

@arkivanov
Copy link
Owner

arkivanov commented Dec 13, 2021

Hello! I never tried custom parcelers in multipaltform. But I think expect/actual should work fine.

// commonMain
expect data class User(...) : Parcelable

// androidMain
@Parcelize
actual data class User(...) : Parcelable {
    // Custom Parceler here
}

// Other source sets
actual data class User(...) : Parcelable

Please let me know if there are any issues.

@arkivanov
Copy link
Owner

Closing this for now. Feel free to reopen if there are any questions.

@gnawf
Copy link
Author

gnawf commented Jan 12, 2022

Oh sorry, yes your suggestion worked 😄. From memory though, it involved a little bit of boilerplate, so a multiplatform option built into Essenty would be nice.

@xxfast
Copy link
Contributor

xxfast commented May 11, 2022

would be nice if we can support TypeParceler<ExternalClass, ExternalClassParceler> in common code, but totally understand if we cant

@arkivanov
Copy link
Owner

@xxfast This would require expect/actual the whole Parcel class. Meantime, it's possible to expect/actual custom parcelers in the following way.

// commonMain

expect interface Parceler<T>

@OptIn(ExperimentalMultiplatform::class)
@OptionalExpectation
@Target(AnnotationTarget.TYPE)
expect annotation class WriteWith<P : Parceler<*>>()
// androidMain

actual typealias Parceler<T> = kotlinx.parcelize.Parceler<T>

actual typealias WriteWith<P> = kotlinx.parcelize.WriteWith<P>
// nonAndroidMain - a shared source source for al targets except Android

actual interface Parceler<T>

After that you can expect/actual your custom parcelers as follows.

// commonMain

class ExternalClass(val value: Int)

expect object ExternalClassParceler : Parceler<ExternalClass>

@Parcelize
class MyClass(val external: @WriteWith<ExternalClassParceler> ExternalClass) : Parcelable
// androidMain

actual object ExternalClassParceler : Parceler<ExternalClass> {
    override fun create(parcel: Parcel): ExternalClass = ExternalClass(parcel.readInt())

    override fun ExternalClass.write(parcel: Parcel, flags: Int) {
        parcel.writeInt(value)
    }
}
// nonAndroidMain

actual object ExternalClassParceler : Parceler<ExternalClass>

Yes, there is some boilerplate, but at least it works. It should be also possible to expect/actual Parcel, with only required methods. In this case Parcelerwould be placed fully incommonMainwithout expect/actual. And so custom parcelers could be placed incommonMain` as well.

Repository owner locked and limited conversation to collaborators May 12, 2022
@arkivanov arkivanov converted this issue into discussion #47 May 12, 2022

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants