Android Kotlin StringRes quantityString

#kotlin #illegalstateexception

#kotlin #illegalstateexception

Вопрос:

Хорошо, так что это:

 fun Context.quantityFromRes(id_: Int, qtt:Int, vararg format: Any) = resources.getQuantityString(id_, qtt, format)
 

xml:

 <plurals name="header_view">
        <item quantity="one">Oh no! You just lost %1$d Point</item>
        <item quantity="other">Oh no! You just lost %1$d Points</item>
    </plurals>
 

Выдает эту ошибку:

 "java.util.IllegalFormatConversionException: %d can't format [Ljava.lang.Object; arguments"
 

Очевидное исправление Java:

 public class XmlPluralFormatter {
    private XmlPluralFormatter() {
        throw new IllegalStateException("You can't fuck me =(");
    }

    public static String getFormattedString(Context context, int stringRes, int qtt, Object... formatArgs){
        return context.getResources().getQuantityString(stringRes,qtt, formatArgs);
    }

    public static String getFormattedString(Context context, int stringRes, int qtt){
        return context.getResources().getQuantityString(stringRes,qtt);
    }
}
 
  • Я только что понял, что использование этого через Java решит проблему, но я понятия не имею, есть ли способ Kotlin сделать то же самое.

PS: Забыл вызов:

 val qtt: Int = 123
context.quantityFromRes(R.plurals.header, qty)
 

Я также могу это сделать:

 fun Context.quantityFromRes(id_: Int, qtt:Int, vararg format: Object) = resources.getQuantityString(id_, qtt, format)
 

но тогда

 Required Object, found Int
 

Я также могу привести:

 context.quantityFromRes(R.plurals.header, qty, qt as Object)
 

но также дает:

 "java.util.IllegalFormatConversionException: %d can't format [Ljava.lang.Object; arguments"
 

Кроме того, работает прямое использование кода без функции расширения:

 context.resources.getQuantityString(R.plurals.header, qtt, qtt)
 

Ответ №1:

Проблема в том, что вы передаете format аргумент как один параметр вместо того, чтобы распространять его на Object... args . Метод расширения:

 fun Context.quantityFromRes(id_: Int, qtt:Int, vararg format: Any) = resources.getQuantityString(id_, qtt, format)
 

эквивалентно:

 fun Context.quantityFromRes(id_: Int, qtt: Int, vararg format: Any): String? {
    val args: Array<out Any> = format
    return resources.getQuantityString(id_, qtt, args)
}
 

Что в терминах Java выглядит так:

 public static final String quantityFromRes(Context $receiver, int id_, int qtt, Object... format) {
    return $receiver.getResources().getQuantityString(id_, qtt, new Object[]{format});
}
 

Вместо этого вы хотите использовать оператор распространения:

 fun Context.quantityFromRes(id_: Int, qtt: Int, vararg format: Any): String? {
    return resources.getQuantityString(id_, qtt, *format)
}
 

Комментарии:

1. Использование spread — элегантное решение, спасибо, что указали на это