Обертывание вызова Context.getString с аргументами форматирования приводит к исключению IllegalFormatConversionException - PullRequest
0 голосов
/ 17 апреля 2020

Я пытаюсь создать оболочку для метода 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 форматировать так же, как и при вызовах ...

Какое решение в этом случае?

Ответы [ 2 ]

0 голосов
/ 20 апреля 2020

Я адаптировался к новому стилю вызова

fun Context.string(@StringRes strId: Int, vararg fmtArgs: Any?) = getString(strId, *fmtArgs)

Это работает. После встраивания и деинсталирования обновился кеш сборок gradle, и он начал работать.

0 голосов
/ 17 апреля 2020

Первый и последний примеры передают массив в качестве первого параметра, потому что отсутствует оператор распространения *, и компилятор в порядке с ним, потому что vararg fmtArgs: Any? это Array<Any?>, но также Any.
getString(strId, *fmtArgs) должно было сработать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...