简体   繁体   English

getSerializableExtra 已弃用,有什么替代方案?

[英]getSerializableExtra deprecated, What is the alternative?

I have upgraded targetSdkVersion and compileSdkVersion to 33 .我已经将targetSdkVersioncompileSdkVersion升级到33

Now getting warning getSerializableExtra and getParcelableExtra are deprecated.现在收到警告getSerializableExtragetParcelableExtra已弃用。

I checked and confirmed from here that it is deprecated.从这里检查并确认它已被弃用。

It is suggested to use updated getSerializableExtra and getParcelableExtra .建议使用更新getSerializableExtragetParcelableExtra Anyone can help me to use the updated method.任何人都可以帮助我使用更新的方法。

  1. Warning while getting an Object :收到Object时发出警告:

getSerializableExtra_Deprecated_Image

  1. Warning while getting an List or ArrayList :获取ListArrayList时发出警告:

getSerializableExtra_Deprecated_List_Image

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. T getSerializableExtra(String, Class<T>)所以我认为你可以按如下方式使用它。

val myPOJOClass = intent.getSerializableExtra("my_intent_key", MyPOJOClass::class.java)

method T getSerializableExtra(String, Class<T>) is introduced from android 33. so you shoud use an if block for devices using android below 33.方法T getSerializableExtra(String, Class<T>)是从 android 33 引入的。因此对于使用 android 低于 33 的设备,您应该使用 if 块。

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)

Inspired by Mohamad's answer, you can do an extension受 Mohamad 回答的启发,您可以进行扩展

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)

However, Mohamad Seyedi's answer did the job.然而, Mohamad Seyedi 的回答起到了作用。 But it fails in the case of getting intent data from onActivityResult() .但是在从onActivityResult()获取意图数据的情况下它会失败。

We can't get data using Activity's intent inside onActivityResult() .我们无法在onActivityResult()中使用 Activity 的意图获取数据。 Below are the solutions I got.以下是我得到的解决方案。

Solution 1: Using extension function:解决方案 1:使用扩展 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:解决方案 2:使用常规 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)

 val myPojoClass = getSerializable(intent, "key_name_here", MyPojoTypeClass::class.java)

then, create that function然后,创建 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 }

This is what I use:这就是我使用的:

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

inline fun <reified T> Intent.serializable(key: String): T? = when {
  SDK_INT >= 33 -> getSerializable(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我也在这里为getParcelable编写了相同的内容,并要求将其直接添加到支持库

For those of us who still use Java, this function does the trick:对于我们这些仍在使用 Java 的人来说,这个 function 可以解决问题:

@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;
}

You can use top functions to serialize arguments您可以使用顶级函数序列化 arguments

but I had a problem serializing the List of object但是我在序列化 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因为List不是Serializable Class,需要转为支持serializable的ArrayList

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现在可以通过这种方式序列化您的列表 object

   override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    requireArguments().serializable<ArrayList<YourObject>>(LIST_KEY)?.let{
        list = it.toList()
    }
   
 }

   

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM