kotlin 不建议使用getSerializableExtra和getParcelableExtra,还有什么办法呢?

i86rm4rw  于 2023-08-06  发布在  Kotlin
关注(0)|答案(8)|浏览(559)

我已经将targetSdkVersioncompileSdkVersion升级到33
我现在收到警告,告诉我getSerializableExtra(name:)和getParcelableExtra(name:)方法已被弃用。
我从Intent类的文档中检查并确认了这两个方法确实已被弃用。
文档建议我使用新的getSerializableExtra(name:clazz:)和getParcelableExtra(name:clazz:)方法。
谁能帮我用新方法?

警告示例

1.获取Object时的警告:


的数据
1.获取ListArrayList时出现警告:


du7egjpx

du7egjpx1#

这就是我使用的:

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
}

字符串
我也在这里为getParcelable编写了相同的代码,并请求将其添加到Support libraries directly中。

7ajki6be

7ajki6be2#

方法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
}

字符串
然后你可以像这样在你的活动中使用它:

val myPOJOClass = getSerializable(this, "my_intent_key", MyPOJOClass::class.java)

aij0ehis

aij0ehis3#

但是,Mohamad Seyedi's回答完成了这项工作。但在**onActivityResult()**获取intent数据时失败。

**onActivityResult()**内部无法使用Activity的Intent获取数据。下面是我得到的解决方案。
解决方案1:使用扩展函数:

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
}

字符串

用法:

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

解决方案2:使用常规函数:

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
}

用法:

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

fslejnso

fslejnso4#

对于我们这些仍然使用Java的人来说,这个函数可以做到这一点:

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

字符串

yhxst69z

yhxst69z5#

受穆罕默德回答的启发,你可以做一个延伸

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)
}

字符串
在任何地方都这样称呼它:

arguments?.getSerializableCompat("my_key", MyClass::class.java)

f0brbegy

f0brbegy6#

我自己还没用过呢。正如文档所述,更新后的方法是
所以你可以使用它如下,我想.

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

字符串

hm2xizp9

hm2xizp97#

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

字符串
然后创建该函数

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
    }

iqxoj9l9

iqxoj9l98#

可以使用top函数序列化参数
但我在序列化对象列表时遇到问题
您可以使用这种方式放置和获取序列化的参数数据
由于List不是可序列化类,因此需要将其转换为支持可序列化的Array List
这些函数用于可序列化

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
    }

字符串
这样handle就把对象的序列化列表

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
       }

   }


现在可以通过这种方式序列化列表对象

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

相关问题