Simple library is great and i already parsed many
different XML from soap servers since last 3 days, but i encountered
boolean attributes with "0" or "1" :
<list mybool1="0" mybool2="1" attr1="attr" attr2="attr">
<page mybool3="1">
...
</page>
<page mybool3="0">
...
</page>
...
</list>
I tried to create this class :
public class Boolean01Converter implements Converter<Boolean>
{
#Override
public Boolean read(InputNode node) throws Exception {
return new Boolean(node.getValue().equals("1"));
}
#Override
public void write(OutputNode node, Boolean value) throws Exception {
node.setValue(value.booleanValue()?"1":"0");
}
}
and implemented it on my object definition :
#Root(name="list")
public class ListFcts
{
#Attribute
#Convert(Boolean01Converter.class)
private Boolean mybool1;
#Attribute
#Convert(Boolean01Converter.class)
private Boolean mybool2;
#Attribute
private int ...
#ElementList(name="page", inline=true)
private List<Page> pages;
public Boolean getMybool1() {
return mybool1;
}
}
But i still get false for every boolean.
[edit]
In fact, when i do this :
#Override
public Boolean read(InputNode node) throws Exception {
return true;
}
i still get false for :
Serializer serial = new Persister();
ListFcts listFct = serial.read(ListFcts.class, soapResult);
if(listFct.getMybool1())
{
//this never happens
}else{
//this is always the case
}
so my Converter has no impact...
Also : how can I attach the converter to the Persister instead of
declaring it on #Attributes hundred times ?
Many thanks in advance !!
[edit2]
i give up with Converter, this is my own solution :
#Root(name="list")
public class ListFcts
{
#Attribute
private int mybool1;
#Attribute
private int mybool2;
public int getMybool1() {
return mybool1;
}
public Boolean isMybool1() {
return (mybool1==1)?true:false;
}
...
}
Your code is using node.getValue() which returns the value (read: contents) of each XML node (the "..." bit in your examples).
What you need is to reading the attribute values, something like node.getAttributeValue("mybool1").equals("1")
i gave up with Converter, I heard about Transform but didn't find how to use it so this is my own basic solution :
#Root(name="list")
public class ListFcts
{
#Attribute
private int mybool1;
#Attribute
private int mybool2;
public int getMybool1() {
return mybool1;
}
public Boolean isMybool1() {
return (mybool1==1)?true:false;
}
...
}
Related
In my Activity, I have a Training object member initialized during onCreate(). All the members of this object are set.
private Training mTraining; is a class member
public class Training extends BaseModel {
...
#SerializedName("state")
public TrainingState state;
....
public TrainingPreview() {
}
This object is got from server (JSON), and I had a converter on this state to ensure this enum can't be null (I use GSON engine):
public class TrainingStateConverter extends EnumConverter<TrainingState> {
public static final Type TYPE = new TypeToken<TrainingState>() {}.getType();
#Override
protected TrainingState deserialize(String value) {
return TrainingState.fromString(value);
}
#Override
protected TrainingState getUnknownValue() {
return TrainingState.UNKNOWN;
}
}
During the setup, I've created the exercise list with the listener to show a specific exercise:
private void refreshExercisesList() {
final Runnable showTrainingParts = new Runnable() {
public void run() {
int nbItems = mCardExercises.setExercises(mTraining.training, mTraining.state,
new FlatCardTrainingProfilePartExercisesView.OnClickExerciseListener() {
#Override
public void showPart(String trainingPartId, int index) {
onClickOnExercisesList(trainingPartId, index);
}
});
}
};
}
...
}
My onClickOnExercisesList() method:
private void onClickOnExercisesList(String trainingPartId, int index) {
...
switch (mTraining.state) {
...
This Activity code works perfectly since couple of months, but yesterday there was a NullPointerException on switch (mTraining.state) :
int com.xxx.model.training.TrainingState.ordinal()' on a null object reference
com.xxx.ui.training.TrainingActivity.onClickOnExercisesList
How is possible guys?
Thank you very much for your help!
This would occur if state did not appear in the JSON.
The TypeConverter is only used if there is a value in the JSON to convert. If the value isn't present, then there's nothing to convert, so the value is whatever the default is, which is null, because you didn't set it:
#SerializedName("state")
public TrainingState state;
To fix the issue, initialize the variable to a default value:
#SerializedName("state")
public TrainingState state = TrainingState.UNKNOWN;
I'm adding an existing Xamarin.Android .NET library to a native Android Studio project. I'm following the indications on https://learn.microsoft.com/en-us/xamarin/tools/dotnet-embedding/ and everything works well, but I have a question not being a Java expert:
is it also possible to export to Java the C#'s properties and actions present in my libraries (like ReturnAnyText)?
namespace export_test
{
[Register("export_test.ClassToExport")]
public class ClassToExport
{
[Export("ClassToExport")]
public ClassToExport()
{
// ...
}
[Export("DoSomething")]
public void DoSomething()
{
// ...
}
public Action<string> ReturnAnyText { get; set;}
}
}
A property under the hood are just get_PropertyName() and set_PropertyName() methods. So yes, you should be able to export those too:
This would look something like:
public bool MyProp
{
[Export]
get;
[Export]
set;
}
Or if you want to name them:
public bool MyProp
{
[Export("GetMyProp")]
get;
[Export("SetMyProp")]
set;
}
The simplest solution I found is to not try to export C# delegates, and simply return an object containing the return values at the end of the method execution:
namespace export_test
{
[Register("export_test.ClassToExport")]
public class ClassToExport
{
[Export("ClassToExport")]
public ClassToExport()
{
// ...
}
[Export("DoSomething")]
public MyResult DoSomething()
{
// ...
}
}
[Register("export_test.MyResult")]
public class MyResult
{
private string _Text;
private int _Value;
[Export("MyResult")]
public MyResult(string text, int val)
{
_Text = text;
_Value = val;
}
[Export("GetText")]
public string GetText() { return _Text; }
[Export("GetValue")]
public int GetValue() { return _Value; }
}
}
How can i achieve this without getting
error: cannot inherit from final ArraySet
ArraySet<MyObject>objectList = new ArraySet<MyObject>(){
#Override
public boolean equals(Object object) {
return ((MyObject)this).getId()==((MyObject)object ).getId();
}
};
ArraySet is a final class, meaning you can't inherit from it. You are trying to create an anonymous subclass when you write
ArraySet<MyObject>objectList = new ArraySet<MyObject>(){
#Override
public boolean equals(Object object) {
return ((MyObject)this).getId()==((MyObject)object ).getId();
}
};
What you really want to do is implement equals (and hashcode) for MyObject:
public class MyObject {
...
#Override
public boolean equals(Object other) {
if (other instanceof MyObject) {
return getId() == ((MyObject) other).getId();
}
return false;
}
}
Then, the ArraySet will work as you intend
I used FirebaseRecyclerAdapter to get all the childs of "Pro" using a Model class named " Spacecraft" and now I want to retrieve all the candidates into a child of Pro like "1"
I created a public static "candidat" into "Spacecraft" and I used the setters and getters but still the same error
This is my database:
this is the Model Class
public class Spacecraft{
private String name;
private String desc;
private String last;
private candidat candidat;
public Spacecraft.candidat getCandidat() {
return candidat;
}
public void setCandidat(Spacecraft.candidat candidat) {
this.candidat = candidat;
}
public Spacecraft() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getLast() {
return last;
}
public void setLast(String last) {
this.last = last;
}
public static class candidat{
private String info;
private String namecandid;
public candidat(){}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public String getNamecandid() {
return namecandid;
}
public void setNamecandid(String namecandid) {
this.namecandid = namecandid;
}
}
}
This is my code for FirebaseRecyclerAdapter
#Override
protected void onStart() {
super.onStart();
FirebaseRecyclerAdapter<Spacecraft, candidatviewholder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Spacecraft, candidatviewholder>(
Spacecraft.class,
R.layout.candidat,
candidatviewholder.class,
query){
#Override
protected void populateViewHolder(candidatviewholder viewHolder, Spacecraft model, int position) {
viewHolder.setName1(model.getCandidat().getNamecandid());
viewHolder.setInfo1(model.getCandidat().getInfo());
}
};
rv.setAdapter(firebaseRecyclerAdapter);
}
The error:
No setter/field for key1 found on class com.example.ilyas.evotingapplication.Spacecraft$candidat
I had this error but the above solutions didn't fix it. Hopefully, this alternate solution will help others. If you have that error occur for almost every variable, chances are that you have Proguard enabled and it is removing the un-used getter and setter methods. To fix this, add a line similar to this to your proguard-rules.pro file:
-keep class com.example.yourapp.ObjectClass
where ObjectClass is the name of your java object class that is stored to Firebase.
I think it's just that your data models on Firebase and in Java differ.
In your java class, the Spacecraft class has a candidat field of type Candidat. But, in the database, the candidat field is really a nested object (map), containing one key Key1, which value is a Candidat structure.
So, depending on what did you want to achieve:
if you wanted each spacecraft to have exactly one candidat: save the database object properly, so {info: "info 1", namecandid: "name 1"} is saved directly under candidat field, not one level deeper, so the field has type Candidat in the code.
if you wanted each spacecraft to have a few candidats: instead of private Candidat candidat field, it should be typed Map<String, Candidat>, because that's the type it has in your database screenshot.
Work for me:
-keepclassmembers class com.myPackageName.MyClassName { *; }
currently I'm playing with GSON and got into some trouble that I couldn't solve on my own.
I've got these three classes:
One abstract class CustomEntity
public abstract class CustomEntity {
private View customView;
public CustomEntity() {}
public void setCustomView(View customView) {
this.customView = customView;
}
public View getCustomView() {
return customView;
}
}
Another class LastChange which extends from CustomEntity
public class LastChange extends CustomEntity {
public Config config;
public LastChange() {}
#Override
public String toString() {
return "LastChange:" + config.toString();
}
public Config getConfig() {
return config;
}
public void setConfig(Config config) {
this.config = config;
}
}
And a third class Config
public class Config extends CustomEntity {
public String config;
public String nav_items;
public Config() {}
#Override
public String toString() {
return "config data:" + config + ", " + nav_items;
}
public String getConfig() {
return config;
}
public void setConfig(String config) {
this.config = config;
}
public String getNav_items() {
return nav_items;
}
public void setNav_items(String nav_items) {
this.nav_items = nav_items;
}
}
In the MainActivity I've tried to deserialize the following JSON into a LastChange object with GSON.
String lastChangeJson = "{\"config\":{\"config\":\"2016-07-20 15:32:14\",\"nav_items\":\"2016-08-24 12:36:06\"},\"background_images\":{\"background_url_landscape\":\"2015-07-28 17:21:56\",\"background_url\":\"2015-07-28 17:21:56\",\"icon_for_accessory_view\":\"2015-07-28 17:21:56\",\"icon_for_route_view\":\"2015-07-28 17:21:56\",\"background_url_landscape_big\":\"2015-07-28 17:21:56\",\"background_url_big\":\"2015-07-28 17:21:56\"},\"nav_content\":[{\"last_change\":\"2016-06-29 11:06:16\",\"pageId\":\"10262\"},{\"last_change\":\"2016-08-24 12:36:06\",\"pageId\":\"10264\"},{\"last_change\":\"2016-08-09 16:13:03\",\"pageId\":\"10378\"},{\"last_change\":\"2016-08-09 16:13:03\",\"pageId\":\"10263\"},{\"last_change\":\"2016-07-20 15:32:14\",\"pageId\":\"10265\"}]}";
CustomEntity lastChangeEntity = gson.fromJson(lastChangeJson, LastChange.class);
The code above gives me the following exception:
java.lang.SecurityException: Can't make method constructor accessible
at java.lang.reflect.Constructor.setAccessible(Constructor.java:336)
at com.google.gson.internal.ConstructorConstructor.newDefaultConstructor(ConstructorConstructor.java:101)
at com.google.gson.internal.ConstructorConstructor.get(ConstructorConstructor.java:83)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:99)
at com.google.gson.Gson.getAdapter(Gson.java:423)...
But if I remove the attribute "customView" from the class CustomEntity and its getter and setter, the deserialization works fine.
Anybody got an idea on how I can tell GSON to ignore class attributes, if they don't appear in my json?
Thanks in advance.
When building new gson instance:
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
Annotate every field you want to serialize with #Expose:
#Expose
public Config config;
Edit:
One small side note - try to avoid keeping references to views (or any Context-related objects) in your models. You may encounter memory leaks if you persist instances of this model in static way and it smells like mixing presentation and data layers, which is never good thing to do for code readability and maintainability.