在 android 中将 Map 转换为 Bundle
Convert Map to Bundle in android
在 android 中是否有一种无需显式迭代即可将 Map 转换为 Bundle 的简单方法?
为什么?
Firebase returns 通知地图 getData()
。我需要将数据传递给意图。以前GCM给了我一个bundle,所以我不用担心这个。
我想一个好的老式 for 循环是最简单的方法:
Bundle bundle = new Bundle();
for (Map.Entry<String, String> entry : getData().entrySet()) {
bundle.putString(entry.getKey(), entry.getValue());
}
private ArrayList<Bundle> convertMapToBundleList(ArrayList<HashMap<String, String>> mapList)
您可以使用 writeToParcel(Parcel out, int flags)
生成一个可能同样有用的 Parcel
,因为它是 Bundle
的父级 class,并且可以方便地内置到 Firebase 中作为 RemoteMessage
class 框架的一部分。文档是 here.
在使用 firebase 消息传递时遇到了同样的问题,并为其创建了一个 kotlin 扩展函数。 gist is here,代码如下。虽然我使用的是这种方法,但有一些注意事项:
- 它没有涵盖所有可以放入捆绑包的类型
- 它仍在开发中,尚未经过全面测试
考虑到这一点,请将其用作指南而不是最终解决方案。随着要点的发展,我会及时更新要点。
import android.os.Bundle
import android.os.IBinder
import android.os.Parcelable
import java.io.Serializable
fun <V> Map<String, V>.toBundle(bundle: Bundle = Bundle()): Bundle = bundle.apply {
forEach {
val k = it.key
val v = it.value
when (v) {
is IBinder -> putBinder(k, v)
is Bundle -> putBundle(k, v)
is Byte -> putByte(k, v)
is ByteArray -> putByteArray(k, v)
is Char -> putChar(k, v)
is CharArray -> putCharArray(k, v)
is CharSequence -> putCharSequence(k, v)
is Float -> putFloat(k, v)
is FloatArray -> putFloatArray(k, v)
is Parcelable -> putParcelable(k, v)
is Serializable -> putSerializable(k, v)
is Short -> putShort(k, v)
is ShortArray -> putShortArray(k, v)
// is Size -> putSize(k, v) //api 21
// is SizeF -> putSizeF(k, v) //api 21
else -> throw IllegalArgumentException("$v is of a type that is not currently supported")
// is Array<*> -> TODO()
// is List<*> -> TODO()
}
}
}
这是我在 Kotlin 中的做法
val bundle = Bundle()
for (entry in data.entries)
bundle.putString(entry.key, entry.value)
现在您可以使用 fun bundleOf(vararg pairs: Pair<String, Any?>)
使用扩展运算符的整洁 Kotlin 解决方案如下所示:
fun Map<String, Any?>.toBundle(): Bundle = bundleOf(*this.toList().toTypedArray())
供日后参考
Convert Map to String
fun Map<String, String>.convertExtraMapToString(): String? {
return keys.stream()
.map { key: String -> "$key=" + this[key] }.collect(Collectors.joining(", ", "{", "}"))
}
Convert String to Map then to Bundle
fun String.convertExtraMapToBundle(): Bundle {
return Arrays.stream(split(",".toRegex()).toTypedArray())
.map { entry: String -> entry.split("=".toRegex()).toTypedArray() }
.collect(Collectors.toMap(
{ entry: Array<String> -> entry[0] }) { entry: Array<String> -> entry[1] }).let {
bundleOf(*it.toList().toTypedArray())
}
}
在 Kotlin 中,您可以构建一个函数扩展来将 Map 转换为 Bundle,而无需像这样进行显式迭代:
override fun onMessageReceived(remoteMessage: RemoteMessage) {
val payload = remoteMessage.data.toBundle()
Log.d(TAG, "Notification payload: $payload")
// ...
}
其中 toBundle() 定义如下:
inline fun <reified T> Map<String, T>.toBundle(): Bundle = bundleOf(*toList<String, T?>().toTypedArray())
或再次:
inline fun <reified T> Map<String, T>.toBundle(): Bundle = bundleOf(*map { it.key to it.value }.toTypedArray())
在 android 中是否有一种无需显式迭代即可将 Map 转换为 Bundle 的简单方法?
为什么?
Firebase returns 通知地图 getData()
。我需要将数据传递给意图。以前GCM给了我一个bundle,所以我不用担心这个。
我想一个好的老式 for 循环是最简单的方法:
Bundle bundle = new Bundle();
for (Map.Entry<String, String> entry : getData().entrySet()) {
bundle.putString(entry.getKey(), entry.getValue());
}
private ArrayList<Bundle> convertMapToBundleList(ArrayList<HashMap<String, String>> mapList)
您可以使用 writeToParcel(Parcel out, int flags)
生成一个可能同样有用的 Parcel
,因为它是 Bundle
的父级 class,并且可以方便地内置到 Firebase 中作为 RemoteMessage
class 框架的一部分。文档是 here.
在使用 firebase 消息传递时遇到了同样的问题,并为其创建了一个 kotlin 扩展函数。 gist is here,代码如下。虽然我使用的是这种方法,但有一些注意事项:
- 它没有涵盖所有可以放入捆绑包的类型
- 它仍在开发中,尚未经过全面测试
考虑到这一点,请将其用作指南而不是最终解决方案。随着要点的发展,我会及时更新要点。
import android.os.Bundle
import android.os.IBinder
import android.os.Parcelable
import java.io.Serializable
fun <V> Map<String, V>.toBundle(bundle: Bundle = Bundle()): Bundle = bundle.apply {
forEach {
val k = it.key
val v = it.value
when (v) {
is IBinder -> putBinder(k, v)
is Bundle -> putBundle(k, v)
is Byte -> putByte(k, v)
is ByteArray -> putByteArray(k, v)
is Char -> putChar(k, v)
is CharArray -> putCharArray(k, v)
is CharSequence -> putCharSequence(k, v)
is Float -> putFloat(k, v)
is FloatArray -> putFloatArray(k, v)
is Parcelable -> putParcelable(k, v)
is Serializable -> putSerializable(k, v)
is Short -> putShort(k, v)
is ShortArray -> putShortArray(k, v)
// is Size -> putSize(k, v) //api 21
// is SizeF -> putSizeF(k, v) //api 21
else -> throw IllegalArgumentException("$v is of a type that is not currently supported")
// is Array<*> -> TODO()
// is List<*> -> TODO()
}
}
}
这是我在 Kotlin 中的做法
val bundle = Bundle()
for (entry in data.entries)
bundle.putString(entry.key, entry.value)
现在您可以使用 fun bundleOf(vararg pairs: Pair<String, Any?>)
使用扩展运算符的整洁 Kotlin 解决方案如下所示:
fun Map<String, Any?>.toBundle(): Bundle = bundleOf(*this.toList().toTypedArray())
供日后参考
Convert Map to String
fun Map<String, String>.convertExtraMapToString(): String? {
return keys.stream()
.map { key: String -> "$key=" + this[key] }.collect(Collectors.joining(", ", "{", "}"))
}
Convert String to Map then to Bundle
fun String.convertExtraMapToBundle(): Bundle {
return Arrays.stream(split(",".toRegex()).toTypedArray())
.map { entry: String -> entry.split("=".toRegex()).toTypedArray() }
.collect(Collectors.toMap(
{ entry: Array<String> -> entry[0] }) { entry: Array<String> -> entry[1] }).let {
bundleOf(*it.toList().toTypedArray())
}
}
在 Kotlin 中,您可以构建一个函数扩展来将 Map 转换为 Bundle,而无需像这样进行显式迭代:
override fun onMessageReceived(remoteMessage: RemoteMessage) {
val payload = remoteMessage.data.toBundle()
Log.d(TAG, "Notification payload: $payload")
// ...
}
其中 toBundle() 定义如下:
inline fun <reified T> Map<String, T>.toBundle(): Bundle = bundleOf(*toList<String, T?>().toTypedArray())
或再次:
inline fun <reified T> Map<String, T>.toBundle(): Bundle = bundleOf(*map { it.key to it.value }.toTypedArray())