Can annotation in Android receive two different data type or do the conversion internally? So that it can read both data type. For example a usual annotation:
#StringDef({CheckInReward.NEW, CheckInReward.USED})
#Retention(RetentionPolicy.SOURCE)
public #interface CheckInReward{
String NEW = "NEW";
String USED = "USED"; }
So let say if backend pass me this status in integer format (new = 1, used = 2). But I don't want to create a new annotation file, can I reuse this file but tweak something inside? like
#StringDef({CheckInReward.NEW, CheckInReward.USED})
#IntDef({CheckInReward.new, CheckInReward.used})
#Retention(RetentionPolicy.SOURCE)
public #interface CheckInReward{
String NEW = "NEW";
String USED = "USED";
int new = 1;
int used = 2; }
I don't know is there any similar question but as my searching doesn't show any result. I know this is not the second piece of code is not working. Just an example defining my question.
Related
I'm entering a new codebase and have to understand how it works. There's a BR file that's autogenerated. I think it comes from the Data Binding Library. That BR files contains a lot of values, but I see no way to automatically search for the area in the code from where the content of that file gets specified.
When I have for example:
public static final int currentDate = 35;
public static final int currentEmail = 36;
How do I lookup where the code that results in those variables existing originates?
I see no way to automatically search for the area in the code from
where the content of that file gets specified.
First of all, BR file is auto generated which will not let you know where from the fields generated. Same like you can not search R fields, where they belong to.
But there are normally two types of fields generated in BR file.
1st is <variable defined in your layout.
<variable
name="model"
type="sample.data.Model"/>
2nd is #Bindable fields.
#Bindable
public String getPassword() {
return password;
}
So BR file look like
public class BR {
public static final int _all = 0;
public static final int model = 0;
public static final int password = 1;
}
_all is some default integer which always gets generated.
Usually generated code relies under this path:
path to project/app/build/generated/rs
To check that in Android studio, you can change project structure view
from 'Android' to 'Project' and follow above path to see generated
code.
That's a bit tricky to find. You can right click on a field and choose "Find Usages" but that will only show you where it's used, not where it originates from. The fields in BR.java are generated from methods marked with #Bindable Like
#Bindable
public String getSomeStringValue() {
return "Some arbitrary string.";
}
Which will result in a field in the BR.java file looking like:
public static final int someStringValue = 126;
So to be able to find where something in the BR-file originates from you take what's in the BR.java file and slap on a "get" and then search for it. Myself, I would probably search for #Bindable instead.
I am converting an object to JSON using com.google.code.gson:gson:2.2.4 library by using code:
String json = new GsonBuilder().excludeFieldsWithModifiers(Modifier.PROTECTED).create().toJson(object);
And in the JSON string "serialVersionUID" is added automatically with Long value even if it is not in a model class. I just want to remove serialVersionUID from JSON.
I found this answer. Basically, the serialVersionUID is added by InstantRun, disabling InstantRun solved the issue for me.
One way to get around this is to use GsonBuilder.excludeFieldsWithoutExposeAnnotation then use the #Expose annotation to explicitly mark what is or isn't (de)serialized.
public class SomeClass {
private int field1 = 2;
#Expose private int field2 = 6;
#Expose #SerializedName ("foo") private int field3 = 12;
}
gives you {"field2":6, "foo":12}. The field field1 is excluded because it isn't annotated with #Expose.
Personally, I always use the GsonBuilder.excludeFieldsWithoutExposeAnnotation because it filters out any generated fields (like the Instant Run comment above). If you didn't annotate it with #Expose, it won't be serialized/deserialized.
Another way is to declare the field as transient.
I'm using Retrofit 2 with a SimpleXmlConverter and I am facing an issue when creating a Soap Request Object, that is basically an element with 4 element children each one of them being different datatypes.
Here is the XML output I want to produce. The element order must be respected:
<prf:container>
<prf:aaa>111111111</prf:aaa>
<prf:bbb>true</prf:bbb>
<prf:element>
<prf:ddd>50</prf:ddd>
<prf:eee>false</prf:eee>
</prf:element>
<prf:ccc>textcontent</prf:ccc>
</prf:container>
Now, here is my Android Class, Container.java, representing the Soap Request Object that will be serialized:
#Root (name = "prf:container")
#Order(elements={"prf:aaa", "prf:bbb", "prf:element", "prf:ccc"})
public class Container {
#Element (name = "prf:aaa")
private int aaa;
#Element(name = "prf:bbb")
private boolean bbb;
#Element (name = "prf:element", required = false)
private MyElement myElement;
#Element (name = "prf:ccc", required = false)
private String ccc;
}
According to the Simple XML framework documentation:
By default serialization of fields is done in declaration order.
However, in Android, this is not true, at least in some cases. No matter how I set the field declaration order in my Container class, the output has always the same element order. This is a known bug and as has been reported in other SO posts.
Nonetheless, there is a solution to this issue. The Order annotation.
Read more in the Javadoc.
My problem is that using the Order annotation in my case is not helping. Note that all my elements have a prefix on its name - prf:.
If I remove the prf prefix from all my element names, Order annotation will work properly, and force the XML Serialization to have the defined order. But the output elements won't have the prefix on its name.
But I really need my elements to have the prefix on its name, or else my request will have a 500 response. I also have to have the desired element order in my XML output.
Any solution to this?
Thank you
I know it has been a long item since you posted this question but, I would like to answer your question in case anyone faced the same issue. I solved the same issue by doing the following:
For the XML document to be prepared with the elements in the order you want and if the elements have a prefix, #Order annotation might not work in some cases. In your case, the prefix 'prf' mentioned in the #Order annotation for each element would not work to order them as you desired.
"By default serialization of fields is done in declaration order."
I don't believe this either, especially when you have prefixes for elements. So, I tried changing the Java variable names. I tried naming them in alphabetical order in the same way I needed them in the generated xml. So, in your case, you can change the variable names as follows:
#Root (name = "prf:container")
public class Container {
#Element (name = "prf:aaa")
private int element1;
#Element(name = "prf:bbb")
private boolean element2;
#Element (name = "prf:element", required = false)
private MyElement element3;
#Element (name = "prf:ccc", required = false)
private String element4;
}
This would form the xml document exactly as you wanted. You might wonder that if we change the variable names to be too generic, they are not representing what they actually are but, you can always have getters and setters. For example, in your case you can have:
public void setAaa(String aaa){
this.element1 = aaa;
}
public String getAaa(){
return element1;
}
In the same way you can always generate the classes with alphabetically ordered variables to make sure the generated xml has the elements in the desired format.
Maybe you using #Order with wrong syntax,Alphabetical order is not important. You can try:
#Root (name = "prf:container")
#Order(elements={"prf:container/prf:aaa", "prf:container/prf:bbb", "prf:container/prf:element", "prf:container/prf:ccc"})
public class Container {
#Element (name = "prf:aaa")
private int aaa;
#Element(name = "prf:bbb")
private boolean bbb;
#Element (name = "prf:element", required = false)
private MyElement myElement;
#Element (name = "prf:ccc", required = false)
private String ccc;
}
SimpleXML's auto ordering by alphabetical order is working. But on one condition: the type of those fields should be the same, usually for XML it is String. It took me long time to figure that out, I had different types, and ordering by name didn't work. Since I've changed all fields to String works like a charm.
#Root(name = "sch:CheckPaymentRequest", strict = true)
public class CheckPaymentData {
#Element(name = "sch:payId")
private String Aaa1;
#Element(name = "sch:fromCurrency")
private String Bbb2;
#Element(name = "sch:fromAmount")
private String Ccc3;
...}
I am just wondering what is the format in Zxing.
String format = intent.getStringExtra("SCAN_RESULT_FORMAT");
Do you think I can delete this line of code?
According to the latest version in the trunk:
/**
* Call intent.getStringExtra(RESULT_FORMAT) to determine which barcode format was found.
* See Contents.Format for possible values.
*/
public static final String RESULT_FORMAT = "SCAN_RESULT_FORMAT";
Contents.Format actually doesn't exist (anymore), but browsing through the code it seems fair to assume the "formats" have been replaced by "types". Contents.Type defines the following possibilities:
public static final String TEXT = "TEXT_TYPE";
public static final String EMAIL = "EMAIL_TYPE";
public static final String PHONE = "PHONE_TYPE";
public static final String SMS = "SMS_TYPE";
public static final String CONTACT = "CONTACT_TYPE";
public static final String LOCATION = "LOCATION_TYPE";
In other words: it gives you information about the type of data that is encoded by the scanned barcode. If you don't care about the type, you can simply ignore it.
This is a string naming the format of the barcode scanned, like "QR_CODE" or "UPC_A". Values come from the class BarcodeFormat. Can you remove it? sure, don't write this line of code if you don't need it!
Are you talking about using the intent integrator? If so, this is the kind of barcode that you just scanned. I don't know what your purposes are, but if you want to support more barcodes, you might want to consider this line more important.
I would like to see if I can avoid a lengthy switch or if block by directly converting some strings into an object name. For example, I have a class called Example and I want to [edit] have up to 10 instances of the class Example1, Example2, so on. Can I use something like:
int ExampleNum = 2;
// can be changed to any 1-10 value corresponding to instances
String s = "Example" + String.valueOf(ExampleNum);
Refresh(s);
public void Refresh(Example example){
...
}
Thus I would create a string with the value of Example2 and pass that to my Refresh method.
[edit]
I don't want to use all the instances at once, but rather have other methods that change the int ExampleNum so that when I try to refresh it refreshes the appropriate Example instance.
Rather than saying:
if (ExampleNum == 2)
Refresh(Example2);
I would use the ExampleNum and String to use the right instance name;
Why not use array's instead??
Example[] e = null;
for(int i=1;i<=10;i++)
{
e[i] = new Example();
Refresh(e[i]);
}
Well, your code, as it stands now, doesn't make any sense since you're passing a String to Refresh, which takes an Example object as an argument.
However, if you're asking how you can create the strings Example1, Example2, ... Example 10, you can do this:
for (int i = 1; i <= 10; i++) {
s = "Example" + i;
refresh(s); // assuming this takes a string
}