Я хотел абстрагироваться от получения ресурсов в Android, поэтому я написал класс ResourceProvider
, который фактически предоставляет ресурсы:
@Singleton
class ResourceProvider @Inject constructor(private val context: Context) {
fun getString(@StringRes id: Int): String {
return context.getString(id)
}
fun getString(@StringRes id: Int, vararg formatArgs: Any): String {
return context.getString(id, formatArgs)
}
...
}
Ничего особенного, просто вызов методов на Context
.
У меня проблема, когда я хочу получить строку с параметрами, я создал следующий пример:
var fromContext = requireContext().getString(R.string.one_parameter_string, "Text")
Log.i("fromContext", fromContext)
var fromWrapper = resourceProvider.getString(R.string.one_parameter_string, "Text")
Log.i("fromWrapper", fromWrapper)
fromContext = requireContext().getString(R.string.two_parameter_string, "Text", "Text")
Log.i("fromContext", fromContext)
fromWrapper = resourceProvider.getString(R.string.two_parameter_string, "Text", "Text")
Log.i("fromWrapper", fromWrapper)
Вот строковые ресурсы:
<string formatted="false" name="two_parameter_string">Text with parameters: %s, %s</string>
<string formatted="false" name="one_parameter_string">Text with parameter: %s</string>
Как вы можете видеть, я вызываю те же самые методы непосредственно для Context
и для моего ResourceProvider
класса. Я ожидал бы таких же результатов, но на самом деле это то, что напечатано в консоли:
I/fromContext: Text with parameter: Text
I/fromWrapper: Text with parameter: [Ljava.lang.Object;@6d43f06
I/fromContext: Text with parameters: Text, Text
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: xxx.xxx.xxx, PID: 22963
java.util.MissingFormatArgumentException: Format specifier '%s'
at java.util.Formatter.format(Formatter.java:2522)
at java.util.Formatter.format(Formatter.java:2458)
at java.lang.String.format(String.java:2814)
at android.content.res.Resources.getString(Resources.java:472)
at android.content.Context.getString(Context.java:572)
at xxx.xxx.xxx.utils.ResourceProvider.getString(ResourceProvider.kt:21)
at xxx.xxx.xxx.views.trial.TrialFragment.onViewCreated(TrialFragment.kt:45)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1471)
at androidx.fragment.app.FragmentManagerImpl.addAddedFragments(FragmentManager.java:2646)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2416)
at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2372)
at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273)
at androidx.fragment.app.FragmentManagerImpl$1.run(FragmentManager.java:733)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6944)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
Как вы можете видеть, вызов его напрямую на Context
работает без изъянов, но при вызове того же метода с моей оболочкой он печатает Object.toString()
, а во втором случае происходит сбой.
Вот декомпилированная версия метода getString(@StringRes id: Int, vararg formatArgs: Any)
:
@NotNull
public final String getString(@StringRes int id, @NotNull Object... formatArgs) {
Intrinsics.checkParameterIsNotNull(formatArgs, "formatArgs");
String var10000 = this.context.getString(id, new Object[]{formatArgs});
Intrinsics.checkExpressionValueIsNotNull(var10000, "context.getString(id, formatArgs)");
return var10000;
}
В чем проблема и как ее зарекомендовать?