使用格式化参数包装调用 Context.getString 会导致 IllegalFormatConversionException
Wrapping the call Context.getString with formatting arguments results in a IllegalFormatConversionException
我正在尝试为 Context#getString(id, args)
方法创建一个包装器,因此我编写的代码更少:
fun Context.string(@StringRes strId: Int, vararg fmtArgs: Any?) = getString(strId, fmtArgs)
调用函数时会产生以下堆栈跟踪:
2020-04-17 13:26:20.778 24143-24143/mypackage E/ERROR: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:267)
... 45 more
Caused by: java.util.IllegalFormatConversionException: d != [Ljava.lang.Object;
at java.util.Formatter$FormatSpecifier.failConversion(Formatter.java:4403)
at java.util.Formatter$FormatSpecifier.printInteger(Formatter.java:2885)
at java.util.Formatter$FormatSpecifier.print(Formatter.java:2839)
at java.util.Formatter.format(Formatter.java:2524)
at java.util.Formatter.format(Formatter.java:2459)
at java.lang.String.format(String.java:2911)
at android.content.res.Resources.getString(Resources.java:485)
at android.content.Context.getString(Context.java:655)
at mypackage.ktx.ContextKt.string(Context.kt:28)
看到这个问题,我查看了 kotlin.text
以了解他们如何使用参数执行字符串格式化...
/**
* Uses this string as a format string and returns a string obtained by substituting the specified arguments,
* using the default locale.
*/
@kotlin.internal.InlineOnly
public inline fun String.format(vararg args: Any?): String = java.lang.String.format(this, *args)
我适应了新的通话方式
fun Context.string(@StringRes strId: Int, vararg fmtArgs: Any?) = getString(strId, *fmtArgs)
…仍然,它因相同的堆栈跟踪而崩溃。
我决定只获取字符串,然后使用 JetBrains 实现手动格式化它,看看是否有一些我没有想到的内部结构:
fun Context.string(@StringRes strId: Int, vararg fmtArgs: Any?) = getString(strId).format(fmtArgs)
我看到问题是 %d
不对应于一个对象,但是如果 Android 可以设法让这种工作和 kotlin 格式以及类似的调用......
这种情况下的解决方案是什么?
第一个和最后一个示例将数组作为第一个参数传递,因为缺少 *
扩展运算符并且编译器可以接受它,因为 vararg fmtArgs: Any?
是一个 Array<Any?>
,但也是一个Any
.
getString(strId, *fmtArgs)
不过应该有用。
I adapted to the new call-style
fun Context.string(@StringRes strId: Int, vararg fmtArgs: Any?) = getString(strId, *fmtArgs)
这行得通。内联和反内联 gradle 构建缓存刷新后开始工作。
我正在尝试为 Context#getString(id, args)
方法创建一个包装器,因此我编写的代码更少:
fun Context.string(@StringRes strId: Int, vararg fmtArgs: Any?) = getString(strId, fmtArgs)
调用函数时会产生以下堆栈跟踪:
2020-04-17 13:26:20.778 24143-24143/mypackage E/ERROR: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:267)
... 45 more
Caused by: java.util.IllegalFormatConversionException: d != [Ljava.lang.Object;
at java.util.Formatter$FormatSpecifier.failConversion(Formatter.java:4403)
at java.util.Formatter$FormatSpecifier.printInteger(Formatter.java:2885)
at java.util.Formatter$FormatSpecifier.print(Formatter.java:2839)
at java.util.Formatter.format(Formatter.java:2524)
at java.util.Formatter.format(Formatter.java:2459)
at java.lang.String.format(String.java:2911)
at android.content.res.Resources.getString(Resources.java:485)
at android.content.Context.getString(Context.java:655)
at mypackage.ktx.ContextKt.string(Context.kt:28)
看到这个问题,我查看了 kotlin.text
以了解他们如何使用参数执行字符串格式化...
/**
* Uses this string as a format string and returns a string obtained by substituting the specified arguments,
* using the default locale.
*/
@kotlin.internal.InlineOnly
public inline fun String.format(vararg args: Any?): String = java.lang.String.format(this, *args)
我适应了新的通话方式
fun Context.string(@StringRes strId: Int, vararg fmtArgs: Any?) = getString(strId, *fmtArgs)
…仍然,它因相同的堆栈跟踪而崩溃。
我决定只获取字符串,然后使用 JetBrains 实现手动格式化它,看看是否有一些我没有想到的内部结构:
fun Context.string(@StringRes strId: Int, vararg fmtArgs: Any?) = getString(strId).format(fmtArgs)
我看到问题是 %d
不对应于一个对象,但是如果 Android 可以设法让这种工作和 kotlin 格式以及类似的调用......
这种情况下的解决方案是什么?
第一个和最后一个示例将数组作为第一个参数传递,因为缺少 *
扩展运算符并且编译器可以接受它,因为 vararg fmtArgs: Any?
是一个 Array<Any?>
,但也是一个Any
.
getString(strId, *fmtArgs)
不过应该有用。
I adapted to the new call-style
fun Context.string(@StringRes strId: Int, vararg fmtArgs: Any?) = getString(strId, *fmtArgs)
这行得通。内联和反内联 gradle 构建缓存刷新后开始工作。