Passing one or two arguments to a string in strings.xml it's possible doing this:
<string name="test">%1$s from %2$s.</string>
context.getString(R.string.test, name, name2);
result:
Pedro from Pablo.
The problem is that now I need to pass a dynamic amount of arguments, not knowing how much in each case, my idea is to get a result similar to this:
Pedro from Pablo, Paco, Peco, Puco.
It is possible to do it with a XML trick? or the only way is to do it manually with Java code?
Don't think this is possible with Android resources, because the number of arguments to substitute is always fixed, they have a fixed position and there is nothing which could represent a repeating pattern. Only Java methods support an arbitrary number of arguments with String..., where the ... means varargs.
String resources could only be used as far as defining the basic sentence and the repeating pattern, but gluing that together requires custom code - else it won't ever be a truly dynamic substitution.
Passing Information to a Method or a Constructor explains it.
You have to define it through Java only. if you know the no of dynamic content then you can define it in xml. according to your need. you have generate the second argument in loop separated by comma an then pass it to xml.
Related
I am not able to clearly understand what is typed array in kotlin. I have seen the fucntion toTypedArray in kotlin. but did not see any proper definition of it like what exactly it does. Can anyone please explain with an example.
Thanks
Arrays are generic data structures because they can contain different types of elements. You can have Array<Int> or Array<String> for instance.
There is no separate concept of "typed" array. The reason for the name of toTypedArray is (I guess) to distiguish it from toArray() which returns an Array<Any?> (without useful type information about its elements, because everything is a Any? in Kotlin).
The reason why those 2 exist is because arrays on the JVM cannot be created without knowing the element type. This means that, in general, you cannot create an arbitrary array generically because generics are erased at runtime so you wouldn't actually know the correct element type at that time. This is why the simple toArray method either returns Array<Any?> or takes an extra array argument. The extra argument allows to either avoid creating the destination array, or at least provides sufficient type information at runtime to create an array of the same type.
In Kotlin, we can go one step further and actually use reified types to use information that we have at compile time to generate more specific code, such as code that create an array of a specific type (not generically, but directly with the correct element type based on the call site information). This is what toTypedArray does by reifying its type parameter.
if i have levels of named parameters that needs to be passed down, i don't want to typeout the named parameter for ever method eg,
BaseText(text,options)
LargerText(text,options)
MenuText(text,options)
eventually i need to pass this to the Text Widget with the different defaults,
but to write out all of the parameters, and pass each on down seems like alot of work,
how can i get around this.
in JS i would just do
LargerText(text,options){
options = {...defaultOptions,...options}
return BaseText(text,options)
}
If Dart supported spreading map into named arguments, this would either reduce type safety, or introduce overhead checks.
Use objects to get around this. This is exactly what objects are for. With each call a compiler checks if the class is what the method expects and so all the fields present. You would not have this with maps.
My app uses a lot of static text and I'm trying to find an optimal way to persist and display that text. For now, I don't need to focus on localizing the text so, all the text goes into the strings.xml and that presents a lot of formatting nightmares.
Of course, it is not 100% static content, I sometimes have dynamic values in there which in my case can stay within strings.xml so, what is the right way for persisting this static text?
Static text content is exactly what you want to use strings.xml for, and you automatically get the added bonus of easier localization as you can have different strings.xml for the different languages. No code changes required, just different XML files.
Dynamic content is going to be content which changes based on user input. You can still use strings.xml to store the static portion (if any) of that dynamic content. Like the "format" string you may pass to String.format() or something similar.
Use the resources support for this, it is exactly what it was intended to do (and do it efficiently.)
Your comment is contradictory; you say:
For now, I don't need to focus on localizing the text so, all the text goes into the strings.xml
if you don't need Localizing, then why are you using strings.xml?
Of course, the answer is because regardless of localizing, strings.xml is the perfect place for this.
I don't know what kind of nightmares you have with it, but it's not different from any other string:
E.g. of a strings.xml:
<string name="refresh">Refresh</string>
<string name="order_placed" formatted="false">Order Placed: %s</string>
You can later use the same formatter for them:
getString(R.string.order_placed, "3pm")
will output:
Order Placed: 3pm
If you need new lines…
<string name="error">Something bad happened.\nPlease try again.</string>
will output:
Something bad happened.
Please try again.
And so forth.
Additionally, if you have trouble naming your resources, I've been following more or less this idea and despite the shortcomings described at the bottom, they haven't been a big deal with Android Studio fancy refactoring tools.
You could create a class called StaticBuffer or something with a static String array as a data member.
class StaticBuffer
{
static String array[];
}
Then you could initialize it in your onCreate() or any other function and use it.As it is static it's values will reflect the changes that you make everywhere.
Eg :
//Initialization
StaticBuffer.array=new String[10];
//Usage
StaticBuffer.array[0]="Item1";
PS: I got this idea from a friend of mine. :)
i found this problem some time ago, but i solve it using this: getString(), or this: getResources().getString()
but now, for this case, it doesn't works, i think it's because i need to get the string values on a NON ANDROID ACTIVITY CLASS. I need the resource values on a remote connection class, that doesn't extends any kind of activity or service.
how i can acces to the variables from my strings.xml on this normal class?
this is the code where i get the error (it gets an integer, and not the string value)
String a =R.string.totalpermission;
Take a look at these two answers (are the same XD):
How to obtain AssetManager without reference to Context?
How can I get a resource content from a static context?
Just an advice: try to read some basic concepts... it seems you don't understand what the R class is and how to use it. Trust me, you waste less time studying than trying to figure out how things work.
I'll add something to existing answers since I found it very useful.
To get your strings you have to use a Context. Your activity will work just great.
String string = getString(R.string.myString);
But if you have something more complex... for exemple
R.string.result -> "You %1$s %2$d cats"
String result = getString(R.string.result, killed ? "killed": "saved", count);
That would give you a result like that:
You saved 10 cats or You killed 2 cats... and so on. You can pass parameters and positional arguments in strings will get replaced by your arguments in getString.
All Android resources are referenced via a resource ID, like R.string.totalpermission. You can see those numbers in R.java (although there's no reason to ever do that).
In cases of strings, you can easily get those using Context.getString. Bonus: You can even pass optional arguments and add dynamic strings that way. You always have a context - how are you getting called? If you really don't have a context, you can create one for the package your resources are in.
I usually place my keys on an xml and access them with R.string.key_name but someone make me notice that I could have inline strings in the code.
I feel that I might use that key in different places and if I change its name I would just rename in the xml but perhaps that doesn't make too much sense with keys.
What do you think?
Your question conflates two different questions:
Does it make sense to have a single definition of your key?
Does it make sense for this single definition to be within an XML file?
The answer to point 1 is clearly "yes". Duplicating strings used as keys (which need to be the same everywhere for your code to function correctly) is a recipe for pain and heartache.
But what benefit does putting the key in an XML file give you? You're just adding "noise" to your code, and ensuring that whoever reads it has to find, understand and look in at least one additional file.
public static final is the way to go.
Inline literal strings will be a massive pain to change if they get scattered through the code. Localizing them in one place with either the strings.xml or a defining a public final static variable will probably save you a headache later.