getParcelableExtra 方法已弃用

Rab*_*dka 87 android parcelable android-intent

我将Parcelable数据传递到Intent中,并使用getParcelableExtra(name:)方法将其从另一端取出。然而,getParcelableExtra(name:)似乎已被弃用。如何修复弃用警告?或者,还有其他选择吗?我使用compileSdkVersion的值为 33。

代码片段

var data = intent.getParcelableExtra("data")
Run Code Online (Sandbox Code Playgroud)

Nik*_*las 191

以下是我用于Bundle&的两种扩展方法Intent

inline fun <reified T : Parcelable> Intent.parcelable(key: String): T? = when {
  SDK_INT >= 33 -> getParcelableExtra(key, T::class.java)
  else -> @Suppress("DEPRECATION") getParcelableExtra(key) as? T
}

inline fun <reified T : Parcelable> Bundle.parcelable(key: String): T? = when {
  SDK_INT >= 33 -> getParcelable(key, T::class.java)
  else -> @Suppress("DEPRECATION") getParcelable(key) as? T
}

Run Code Online (Sandbox Code Playgroud)

我还要求将其添加到支持库中

如果您需要 ArrayList 支持,可以:

inline fun <reified T : Parcelable> Bundle.parcelableArrayList(key: String): ArrayList<T>? = when {
  SDK_INT >= 33 -> getParcelableArrayList(key, T::class.java)
  else -> @Suppress("DEPRECATION") getParcelableArrayList(key)
}

inline fun <reified T : Parcelable> Intent.parcelableArrayList(key: String): ArrayList<T>? = when {
  SDK_INT >= 33 -> getParcelableArrayListExtra(key, T::class.java)
  else -> @Suppress("DEPRECATION") getParcelableArrayListExtra(key)
}
Run Code Online (Sandbox Code Playgroud)

注意:新方法在 SDK 33 上存在一些问题,因此您可能只想从 SDK 34 开始使用它。

  • Android 13 上似乎存在与此 API 相关的错误。谷歌表示他们将在下一个版本中修复它并提供一些东西。所以,目前,我认为最好使用 `&gt; VERSION_CODES.TIRAMISU` 而不是 `&gt;= VERSION_CODES.TIRAMISU` 。链接:https://issuetracker.google.com/issues/240585930#comment6 (4认同)

Nil*_*hod 43

现在我们需要使用getParcelableExtra()添加到 API 33 的类型安全类

kotlin 的示例代码

val userData = if (VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
  intent.getParcelableExtra("DATA", User::class.java)
} else {
  intent.getParcelableExtra<User>("DATA")
}
Run Code Online (Sandbox Code Playgroud)

JAVA 示例代码

if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
  user = getIntent().getParcelableExtra("data", User.class);
} else {
  user = getIntent().getParcelableExtra("data");
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*cko 36

androidx.core:core-ktx:1.10.0提供了两个类IntentCompatBundleCompat一些有用的静态方法

androidx.core.os.BundleCompat

BundleCompat.getParcelable(Bundle, String, Class<T>)
BundleCompat.getParcelableArray(Bundle, String, Class<? extends Parcelable>): Parcelable[] 
BundleCompat.getParcelableArrayList(Bundle, String, Class<? extends T> clazz): ArrayList<T>
BundleCompat.getSparseParcelableArray(Bundle, String, Class<? extends T>): SparseArray<T>
Run Code Online (Sandbox Code Playgroud)

androidx.core.content.IntentCompat

IntentCompat.getParcelableExtra(Intent, String, Class<T>)
IntentCompat.getParcelableArrayExtra(Intent, String, Class<? extends Parcelable>): Parcelable[]
IntentCompat.getParcelableArrayListExtra(Intent, String, Class<? extends T>): ArrayList<T>
Run Code Online (Sandbox Code Playgroud)

检索 对象的示例android.bluetooth.BluetoothDevice

IntentCompat.getParcelableExtra(intent, BluetoothDevice.EXTRA_DEVICE, BluetoothDevice::class.java) 
Run Code Online (Sandbox Code Playgroud)

@Niklas 提出的扩展的简化版本:

inline fun <reified T : Parcelable> Bundle.parcelable(key: String): T? =
    BundleCompat.getParcelable(this, key, T::class.java)

inline fun <reified T : Parcelable> Intent.parcelable(key: String): T? =
    IntentCompat.getParcelableExtra(this, key, T::class.java)
Run Code Online (Sandbox Code Playgroud)

对于数组列表:

inline fun <reified T : Parcelable> Bundle.parcelableList(key: String): List<T>? =
    BundleCompat.getParcelableArrayList(this, key, T::class.java)

inline fun <reified T : Parcelable> Intent.parcelableList(key: String): List<T>? =
    IntentCompat.getParcelableArrayListExtra(this, key, T::class.java)
Run Code Online (Sandbox Code Playgroud)

  • 对于捆绑包:`BundleCompat.getParcelable` (6认同)
  • 使用兼容类似乎是正确的答案。 (2认同)

Mar*_*ler 8

例如,在 Java 中:

UsbDevice device;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.S_V2) { // TIRAMISU onwards
    device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE, UsbDevice.class);
} else {
    device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
}
Run Code Online (Sandbox Code Playgroud)

这还是需要的@SuppressWarnings({"deprecation", "RedundantSuppression"})

  • @MBH 没有。上面的代码是正确的。它可以是`SDK_INT &gt; S_V2`(大于32)或`SDK_INT &gt;= TIRAMISU`(大于或等于33)。 (2认同)

ged*_*lod 7

正如官方文档中所述,getParcelableExtra在 API 级别 33 中已弃用。

因此检查 API LEVEL 是否 >= 33 或更改方法,

...

if (Build.VERSION.SDK_INT >= 33) { // TIRAMISU
    data = intent.getParcelableExtra (String name, Class<T> clazz)
}else{
    data = intent.getParcelableExtra("")
}
Run Code Online (Sandbox Code Playgroud)

这是使用 android.bluetooth.BluetoothDevice 的示例

...
val device = if (Build.VERSION.SDK_INT >= 33){ // TIRAMISU
    intent.getParcelableArrayExtra(
        BluetoothDevice.EXTRA_NAME,
        BluetoothDevice::class.java
    )
}else{
    intent.getParcelableExtra(BluetoothDevice.EXTRA_NAME)
}
Run Code Online (Sandbox Code Playgroud)

  • 我不明白你在这里的意思是什么。`getParcelableExtra (String name, Class&lt;T&gt; clazz)` 没有任何意义。 (4认同)