问题始于
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
充满意图的课程
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
如何接受不同类型的数组并假装喜欢它?
由于以下几个原因,这是一团糟:
Parcelable
、Bundle
、Intent
、ArrayList
)实际上是 Java我会把问题分成两部分:
ArrayList
解包为 ArrayList<Parcelable>
ArrayList<Parcelable>
的内容为期望的类型检查 API 级别和相应的代码:
if (Build.VERSION.SDK_INT >= 33) {
data = intent.getParcelableExtra (String name, Class<T> clazz)
}else{
data = intent.getParcelableExtra("data")
}
您还可以将这些扩展用于捆绑和意图:
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
}
您不需要将 ParcelableArrayList 转换为 ArrayList,而是在检索它时使用 ArrayList 创建它,就像发出额外内容一样:
mUserList = ArrayList<UserClass>(getParcelableArrayListExtra(EXTRA_PAYMENT_OPTIONS_EXTRA))