android getParcelableArrayListExtra会导致为变量设置不同的类型

uqxowvwt  于 2022-12-31  发布在  Android
关注(0)|答案(2)|浏览(220)

问题是getParcelableArrayListExtra不支持类型检查,当我们试图将它设置为变量时,让我给予一个尽可能基本的例子。
用户类。

import kotlinx.parcelize.Parcelize
import android.os.Parcelable

    @Parcelize
    data class UserClass(
            var name: String? = null,
            var text: String? = null,
            var age: Int? = null
    ) : Parcelable

我们将尝试设置为User变量的随机类。

import android.os.Parcelable
import kotlinx.parcelize.Parcelize

@Parcelize
data class MessageClass(
    val title: String?, = Constant.STRING_EMPTY
    val text: String? = Constant.STRING_EMPTY
) : Parcelable

填充Intent的类

class FillIntentClass(){

    //Let's say one of the developers added the MessageClass object inside our intent.
    //Or BE sent the wrong type of object and I passed its value to the intent.
    private fun DummyFunctionToSetIntent(){

    val messageList = arraylistOf(MessageClass(title = "hello",text ="dummy text")

    intent.putParcelableArrayListExtra(EXTRA_PAYMENT_OPTIONS_EXTRA, messageList)
  }   
}

试验类别

class MyTestClass(){
  // UserList variable 
   private var mUserList: ArrayList<UserClass>? = null


   override fun onCreate(savedInstanceState: Bundle?) {
        ...
     with(intent) {
     // In this situation, mUserList became the type of ArrayList<MessageClass>
     // But it shouldn't be possible. Because it must accept only ArrayList<UserClass>
     // And that causes mostly crashes when the other code parts use it.
     mUserList = getParcelableArrayListExtra(EXTRA_PAYMENT_OPTIONS_EXTRA)
     // mUserList now pretend its like ArrayList<MessageClass>. But i set it as ArrayList<UserClass> at the top of the class.

     // The best way to solve this is to type check with as?. If the type is not as expected it must return null.
     // But I cannot use type check here. It gives me a "Not enough information to infer type variable T" error.
     mUserList = getParcelableArrayListExtra(EXTRA_PAYMENT_OPTIONS_EXTRA) as? ArrayList<UserClass> //(compile error here on IDE)

     // So I had to come out with the below solution. But I cannot say it's the best practice.
     if (getParcelableArrayListExtra<UserClass>(EXTRA_PAYMENT_OPTIONS_EXTRA)
            ?.filterIsInstance<UserClass>()?.isNotEmpty() == true
    ) {
        mUserList = getParcelableArrayListExtra(EXTRA_PAYMENT_OPTIONS_EXTRA)
      }
    }
  }
}

类型检查(as,as?)可以像预期的那样使用getParcelable函数,但是当它使用getParcelableArrayListExtra时,它就不起作用了,并且会产生编译错误,正如我上面解释的那样。
你知道什么是as, as?检查的最佳选择吗?mUserList如何可能接受不同类型的数组并假装它?

tyu7yeag

tyu7yeag1#

这是一个烂摊子,原因有几个:

  • 您使用的是Kotlin语言,但您处理的类(ParcelableBundleIntentArrayList)实际上是Java
  • Java中的泛型是一种

我将把问题分成两部分:
1.将ArrayList解包为ArrayList<Parcelable>
1.检查ArrayList<Parcelable>的内容/将其转换为预期类型

ldioqlga

ldioqlga2#

相应地检查API级别和代码:

if (Build.VERSION.SDK_INT >= 33) { 
    data = intent.getParcelableExtra (String name, Class<T> clazz)
}else{
    data = intent.getParcelableExtra("data")
}

您还可以将这些扩展用于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
}

相关问题