在 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())