【问题标题】:Print the contents of a Bundle to Logcat?将Bundle的内容打印到Logcat?
【发布时间】:2013-02-19 02:13:19
【问题描述】:

如果您不记得所有键的名称,有没有一种简单的方法可以将 Bundle 的内容打印到 Logcat(即使只打印键名也很酷)?

【问题讨论】:

    标签: java android logcat android-bundle


    【解决方案1】:

    Bundle#keySet() 应该可以工作。

    for (String key: bundle.keySet())
    {
      Log.d ("myApplication", key + " is a key in the bundle");
    }
    

    如果你想获取Object,你可以使用Bundle#get(String key)(which is also in the same documentation I linked at the top of my answer)。但是,请记住使用通用的get() 调用:

    • 您正在使用 Object。如果您只是打印到日志,toString() 将被调用,一切都会好起来的。但是,如果您确实想使用密钥对,则需要进行instanceof 检查以避免调用错误的方法。
    • 由于 toString 将被调用,如果您有一个特殊的对象(例如 ArrayLists,或特殊的 Serializable/Parcelable extras),您很可能不会从打印输出中得到任何有用的信息。

    【讨论】:

    • 我认为您的意思是bundle.keySet()(因为您的文档链接很好);否则这是正确的。
    • @Eric gah,愚蠢的错误。至少我在链接时拼写正确。
    【解决方案2】:

    您可以通过如下方式打印映射值来获得更具体的信息:

    for (String key : bundle.keySet())
    {
        Log.d("Bundle Debug", key + " = \"" + bundle.get(key) + "\"");
    }
    

    【讨论】:

      【解决方案3】:

      捆绑到字符串转换器:

      public static String bundle2string(Bundle bundle) {
          if (bundle == null) {
              return null;
          }
          String string = "Bundle{";
          for (String key : bundle.keySet()) {
              string += " " + key + " => " + bundle.get(key) + ";";
          }
          string += " }Bundle";
          return string;
      }
      

      示例用法:

      Log.d(TAG,"details="+bundle2string(details));
      

      和输出:

      details=Bundle{ RESPONSE_CODE => 5; }Bundle
      

      请注意,箭头 => 和分号 ; 让您可以在键和值中提及空格。箭头前一个空格,箭头后一个空格,分号前无空格,分号后一个空格,{ 后一个空格} 前一个空格,所有其他空格都在那里,因为它们在键或值中。

      【讨论】:

      • 很好的解决方案,但我宁愿使用 StringBuffer 以获得更好的性能:public static String bundle2string(Bundle bundle) { StringBuffer buf = new StringBuffer("Bundle{"); for (String key : bundle.keySet()) buf.append(" " + key + " => " + bundle.get(key) + ";"); buf.append(" }Bundle"); return buf.toString(); }
      • IMO 性能与 bundle2string() 的目的无关,但即使我们假设相反,根据stackoverflow.com/a/4649160/755804String 连接被转换为 StringBuilder编译器的操作。我自己没有为Android检查它;如果有人愿意检查这一点,请确认或反驳。
      • @Maurix 由于不涉及线程,因此 StringBuilder 优于 StringBuffer :developer.android.com/reference/java/lang/StringBuffer.html
      • 请注意,某些值可能包含多行,因此在单个日志条目中打印所有值可能会出现问题。
      【解决方案4】:

      意识到这并没有准确回答问题,但我看到很多开发人员试图将内容转储到 logcat/console,因为他们不知道他们可以在 Android Studio 调试器中设置以在调试时显示自定义对象渲染时间,当你遇到一个断点。在 Bundle 的情况下,您可以采用此处其他答案中显示的代码类型,并将其应用为自定义渲染器,这样您就无需将转储通过管道传输到 logcat 和/或控制台。

      (这些说明来自 Android Studio 3.1.3(2018 年 6 月)...

      1. 选择“文件”,然后选择“设置”菜单选项/子选项。
      2. 在左侧的“设置”对话框中,向下钻取并选择“构建、执行、部署”、“调试器”、“数据视图”、“Java 类型渲染器”。
      3. 对话框右侧显示“渲染器名称”,输入您希望与正在创建的渲染器标识的名称。
      4. 在对话框右侧显示“将渲染器应用于对象类型”,输入“android.os.Bundle”。
      5. 对话框右侧的“渲染节点时”部分下,选择“使用以下表达式:”单选按钮。
      6. 在下面的文本字段中,输入以下内容...
      StringBuilder builder = new StringBuilder();
      for (String key : ((android.os.Bundle)this).keySet()) {
          Object value = ((android.os.Bundle)this).get(key);
          builder.append("[");
          builder.append(key);
          builder.append("]=[");
          builder.append(value);
          builder.append("](");
          builder.append((value != null) ? value.getClass().getSimpleName() : "null");
          builder.append("), ");
      }
      return builder.toString();
      
      1. 按“应用”/“确定”按钮。

      现在,当您运行应用程序时,您遇到了一个显示 android.os.Bundle 类型的变量的断点,您将在调试器窗口的变量部分看到上述代码生成的输出.

      我还会附上一个屏幕截图,显示我上面描述的内容...

      【讨论】:

      • 这是我不知道的 Android Studio 的一个非常简洁的功能。谢谢!
      • @Julian A. 不客气。是的,我一直很惊讶它没有被更多地谈论,并希望 Android Studio 不包含为经常使用的类预先创建的表达式,这样可以节省一些时间。仅供参考,对于使用该 IDE 的用户,Eclipse 也有类似的功能。
      • 很棒的提示!事实证明,我们可以将渲染器表达式简化为 keySet(); toString(),因为访问 Bundle 的内容似乎将其具体化,让 toString() 格式化所有元素。查看我的答案。
      【解决方案5】:

      Kotlin 中的简单 Bundle 到 String 的实现:

      val bundleToString = bundle.keySet()
                  .joinToString(", ", "{", "}") { key ->
                      "$key=${bundle[key]}"
                  }
      

      结果示例{id=3, name="Jhon"}

      【讨论】:

      • 谢谢,它有效。键按字母顺序排列(keySet() 返回排序后的集合)。
      【解决方案6】:

      在 Kotlin 中,当它包含子包时递归:

      /**
       * Recursively logs the contents of a [Bundle] for debugging.
       */
      fun Bundle.printDebugLog(parentKey: String = "") {
          if (keySet().isEmpty()) {
              Log.d("printDebugLog", "$parentKey is empty")
          } else {
              for (key in keySet()) {
              when (val value = this[key]) {
                      is Bundle -> value.printDebugLog(key)
                      is Array<*> -> Log.d("printDebugLog", "$parentKey.$key : ${value.joinToString()}")
                      else -> Log.d("printDebugLog", "$parentKey.$key : $value")
                  }
              }
          }
      }
      

      用法:myBundle.printDebugLog()

      【讨论】:

        【解决方案7】:

        我开发了一个名为pretty-print 的库,它的注释处理器以漂亮的表格格式打印捆绑包的内容。 请检查一下 https://github.com/NULLPointerGuy/pretty-print

        【讨论】:

          【解决方案8】:

          Kotlin 解决方案:

          val bundleFromNotifications: Bundle? = remoteMessage?.toIntent()?.extras
          bundleFromNotifications?.keySet()?.forEach{
              Log.d(LOG_TAG, it + "=> \"" + bundleFromNotifications.get(it) + "\"")
          }
          

          【讨论】:

            【解决方案9】:

            技巧:访问 Bundle 的内容以对其进行具体化,然后bundle.toString() 将格式化其元素。

            (我仅将其用于调试目的。)

            AppWidgetProvider 中的示例,调用newOptions.keySet()

                @Override
                public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager,
                        int appWidgetId, Bundle newOptions) {
                    super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
            
                    newOptions.keySet(); // <-- reify the Bundle so .toString() will elaborate
                    Log.i(TAG, "*** WidgetOptionsChanged: " + newOptions);
                }
            

            结果:

            *** WidgetOptionsChanged: Bundle[{appWidgetMaxHeight=137, appWidgetCategory=1, appWidgetMaxWidth=603, appWidgetMinHeight=82, appWidgetMinWidth=338, appWidgetSizes=[338.0x137.5, 603.5x82.0]}]
            

            比:

            *** WidgetOptionsChanged: Bundle[mParcelledData.dataSize=408]
            

            【讨论】:

              【解决方案10】:

              Kotlin 中的解决方案:

              fun Bundle.toPrintableString(): String {
                  val sb = StringBuilder("{")
                  var isFirst = true
                  for (key in keySet()) {
                      if (!isFirst)
                          sb.append(',')
                      else
                          isFirst = false
                      when (val value = get(key)) {
                          is Bundle -> sb.append(key).append(':').append(value.toPrintableString())
                          else -> sb.append(key).append(':').append(value)
                          //TODO handle special cases if you wish
                      }
                  }
                  sb.append('}')
                  return sb.toString()
              }
              

              示例:

                  val bundle = Bundle()
                  bundle.putString("asd", "qwe")
                  bundle.putInt("zxc", 123)
                  Log.d("AppLog", "bundle:${bundle.toPrintableString()}")
              

              请注意,它不能处理所有可能类型的值。您应该决定展示哪些重要内容以及展示方式。

              【讨论】:

                【解决方案11】:

                Java 8 流式一班轮:

                bundle.keySet().stream().forEach(k -> Log.d(TAG, k + " = " + bundle.get(k)));
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-04-25
                  • 2015-04-12
                  相关资源
                  最近更新 更多