Reputation: 12579
I have upgraded targetSdkVersion
and compileSdkVersion
to 33
.
I am now getting warnings telling me that the getSerializableExtra(name:) and getParcelableExtra(name:) methods are deprecated.
I checked and confirmed from the documentation in the Intent class that these two methods are indeed deprecated.
The documentation suggests that I use the new getSerializableExtra(name:clazz:) and getParcelableExtra(name:clazz:) methods instead.
Can anyone can help me use the new methods?
Object
:List
or ArrayList
:Upvotes: 60
Views: 59240
Reputation: 10887
There were compatibility functions added within BundleCompat
:
BundleCompat.getSerializable(myBundle, "MySerializableKey", MySerializable::class.java)
BundleCompat.getParcelable(myBundle, "MyParcelableKey", MyParcelable::class.java)
It will behave so that
Bundle.getXYZ(key, T::class.java)
Bundle.getXYZ(key)
and performs a checked castIf the key
does not exist or does not match the expected type, null
is returned.
Upvotes: 0
Reputation: 1467
There is a compat funtion for this:
BundleCompat.getSerializable(bundle, name, clazz)
bundle isn't nullable so intent.extras need to be null checked first.
Upvotes: 0
Reputation: 2817
Since we already have good answers with Serializable, will answer in favour of Parcelable
If you feel BundleComapt and IntentCompat versions are longer you can create extensions like this and use
inline fun <reified T: Parcelable> Bundle.getParcel(key: String): T? =
BundleCompat.getParcelable(this, key, T::class.java)
inline fun <reified T: Parcelable> Intent.getParcel(key: String): T? =
IntentCompat.getParcelableExtra(this, key, T::class.java)
Upvotes: 1
Reputation: 1144
Expanding upon Rumit Patel's answer, using an inline function with reified type parameter, usage is even simpler.
Note that I made the return type nullable, because !!
should in my opinion only be used as a last resort (or at caller side).
@Suppress("DEPRECATION")
inline fun <reified T : Serializable> Intent.getSerializable(key: String): T? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
this.getSerializableExtra(key, T::class.java)
else
this.getSerializableExtra(key) as? T
}
@Suppress("DEPRECATION")
inline fun <reified T : Parcelable> Intent.getParcelable(key: String): T? {
Timber.d("intentextras parce")
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
this.getParcelableExtra(key, T::class.java)
} else {
this.getParcelableExtra(key)
}
}
@Suppress("DEPRECATION")
inline fun <reified T : Parcelable> Intent.getParcelableArrayList(key: String): ArrayList<T>? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
this.getParcelableArrayListExtra(key, T::class.java)
} else {
this.getParcelableArrayListExtra(key)
}
}
Usage:
val mode1: Mode = intent.getSerializable("key")
val mode2 = intent.getSerializable<Mode>("key")
Upvotes: 6
Reputation: 325
You can use top functions to serialize arguments
but I had a problem serializing the List of object
You can use this way to put and get serialized argument data
Because List is not a Serializable Class, you need to convert it to Array List that supports serializable
These functions are used for serializable
inline fun <reified T : Serializable> Bundle.serializable(key: String): T? =
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU ->
getSerializable(key, T::class.java)
else -> @Suppress("DEPRECATION") getSerializable(key) as? T
}
inline fun <reified T : Serializable> Intent.serializable(key: String): T? =
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU ->
getSerializableExtra(key, T::class.java)
else -> @Suppress("DEPRECATION") getSerializableExtra(key) as? T
}
and this way handle puts serialized List of objects
class YourFragment: Fragment {
private latinit var list: List<YourObject>
fun newInstance(
listOfYourObject: List<YourObject>
): YourFragment {
val args = Bundle()
val yourList= ArrayList<YourObject>()
yourList.addAll(listOfYourObject)
args.putSerializable(LIST_KEY, yourList)
val fragment = YourFragment()
fragment.arguments = args
return fragment
}
}
and now can get serialize of your list object in this way
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requireArguments().serializable<ArrayList<YourObject>>(LIST_KEY)?.let{
list = it.toList()
}
}
Upvotes: 0
Reputation: 5480
For those of us who still use Java, this function does the trick:
@SuppressWarnings({"unchecked", "deprecation"})
@Nullable
public static <T extends Serializable> T getSerializable(@Nullable Bundle bundle, @Nullable String key, @NonNull Class<T> clazz) {
if (bundle != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
return bundle.getSerializable(key, clazz);
} else {
try {
return (T) bundle.getSerializable(key);
} catch (Throwable ignored) {
}
}
}
return null;
}
Upvotes: 8
Reputation: 3046
val myPojoClass = getSerializable(intent, "key_name_here", MyPojoTypeClass::class.java)
then, create that function
private fun <T : Serializable?> getSerializable(intent: Intent, key: String, className: Class<T>): T {
return if (Build.VERSION.SDK_INT >= 33)
intent.getSerializableExtra(key, className)!!
else
intent.getSerializableExtra(key) as T
}
Upvotes: 1
Reputation: 25443
This is what I use:
inline fun <reified T : Serializable> Bundle.serializable(key: String): T? = when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> getSerializable(key, T::class.java)
else -> @Suppress("DEPRECATION") getSerializable(key) as? T
}
inline fun <reified T : Serializable> Intent.serializable(key: String): T? = when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> getSerializableExtra(key, T::class.java)
else -> @Suppress("DEPRECATION") getSerializableExtra(key) as? T
}
I've also written the same for getParcelable here and requested this to be added to the Support libraries directly
Upvotes: 75
Reputation: 12579
However, Mohamad Seyedi's answer did the job. But it fails in the case of getting intent data from onActivityResult()
.
We can't get data using Activity's intent inside onActivityResult()
. Below are the solutions I got.
Solution 1: Using extension function:
fun <T : Serializable?> Intent.getSerializable(key: String, m_class: Class<T>): T {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
this.getSerializableExtra(key, m_class)!!
else
this.getSerializableExtra(key) as T
}
Usage:
val myPOJOClass = intent.getSerializable("my_intent_key", MyPOJOClass::class.java)
Solution 2: Using regular function:
fun <T : Serializable?> getSerializable(intent: Intent, key: String, m_class: Class<T>): T {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
intent.getSerializableExtra(key, m_class)!!
else
intent.getSerializableExtra(key) as T
}
Usage:
val myPOJOClass = getSerializable(intent, "my_intent_key", MyPOJOClass::class.java)
Upvotes: 6
Reputation: 2764
Inspired by Mohamad's answer, you can do an extension
fun <T : Serializable?> Bundle.getSerializableCompat(key: String, clazz: Class<T>): T {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) getSerializable(key, clazz)!! else (getSerializable(key) as T)
}
and call it everywhere like this:
arguments?.getSerializableCompat("my_key", MyClass::class.java)
Upvotes: 2
Reputation: 443
method T getSerializableExtra(String, Class<T>)
is introduced from android 33.
so you shoud use an if block for devices using android below 33.
fun <T : Serializable?> getSerializable(activity: Activity, name: String, clazz: Class<T>): T
{
return if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
activity.intent.getSerializableExtra(name, clazz)!!
else
activity.intent.getSerializableExtra(name) as T
}
and then you can use it in your activity like this:
val myPOJOClass = getSerializable(this, "my_intent_key", MyPOJOClass::class.java)
Upvotes: 26
Reputation: 21053
Haven't used it myself till yet . As the doc says the updated method is
T getSerializableExtra(String, Class<T>)
So you can use it as follows i think.
val myPOJOClass = intent.getSerializableExtra("my_intent_key", MyPOJOClass::class.java)
Upvotes: 1