WorkManager Data.Builder does not support Parcelable

前端 未结 6 1100
心在旅途
心在旅途 2021-02-20 06:18

When you have a big POJO with loads of variables (Booleans, Int, Strings) and you want to use the new Work Manager to start a job. You then create a Data file which gets added t

6条回答
  •  悲&欢浪女
    2021-02-20 06:59

    This solution works without using JSON, and serializes directly to byte array.

    package com.andevapps.ontv.extension
    
    import android.os.Parcel
    import android.os.Parcelable
    import androidx.work.Data
    import java.io.*
    
    fun Data.Builder.putParcelable(key: String, parcelable: Parcelable): Data.Builder {
        val parcel = Parcel.obtain()
        try {
            parcelable.writeToParcel(parcel, 0)
            putByteArray(key, parcel.marshall())
        } finally {
            parcel.recycle()
        }
        return this
    }
    
    fun Data.Builder.putParcelableList(key: String, list: List): Data.Builder {
        list.forEachIndexed { i, item ->
            putParcelable("$key$i", item)
        }
        return this
    }
    
    fun Data.Builder.putSerializable(key: String, serializable: Serializable): Data.Builder {
        ByteArrayOutputStream().use { bos ->
            ObjectOutputStream(bos).use { out ->
                out.writeObject(serializable)
                out.flush()
            }
            putByteArray(key, bos.toByteArray())
        }
        return this
    }
    
    @Suppress("UNCHECKED_CAST")
    inline fun  Data.getParcelable(key: String): T? {
        val parcel = Parcel.obtain()
        try {
            val bytes = getByteArray(key) ?: return null
            parcel.unmarshall(bytes, 0, bytes.size)
            parcel.setDataPosition(0)
            val creator = T::class.java.getField("CREATOR").get(null) as Parcelable.Creator
            return creator.createFromParcel(parcel)
        } finally {
            parcel.recycle()
        }
    }
    
    inline fun  Data.getParcelableList(key: String): MutableList {
        val list = mutableListOf()
        with(keyValueMap) {
            while (containsKey("$key${list.size}")) {
                list.add(getParcelable("$key${list.size}") ?: break)
            }
        }
        return list
    }
    
    @Suppress("UNCHECKED_CAST")
    fun  Data.getSerializable(key: String): T? {
        val bytes = getByteArray(key) ?: return null
        ByteArrayInputStream(bytes).use { bis ->
            ObjectInputStream(bis).use { ois ->
                return ois.readObject() as T
            }
        }
    }
    

    Add proguard rule

    -keepclassmembers class * implements android.os.Parcelable {
      public static final android.os.Parcelable$Creator CREATOR;
    }
    

提交回复
热议问题