Android Question SetField of a Type with Reflector or JavaObject ?

Martin D.

Member
Licensed User
Hi, I want to use a type as an enum and I don't want to set the value of each string of that type since the fieldname IS what the string value will be. How to do it with Reflector or JavaObject ?

B4X:
    Dim r As Reflector
    r.Target = BiomeType
    r.Target = r.RunMethod("getClass")
    Dim Fields() As Object = r.RunMethod("getDeclaredFields")
    For Each Field As Object In Fields
           r.Target = Field
        Dim name As String = r.RunMethod("getName")
        If name = "IsInitialized" Then Continue
         r.SetField(name,name, "java.lang.string") <--- error 
    Next
    Next
java.lang.NoSuchFieldException: Desert
at java.lang.Class.getDeclaredField(Class.java:2070)

OR : do you suggest another approach entirely. Thanks !
 

stevel05

Expert
Licensed User
The easiest way is to use a Code Module and set the fields as Public Const, they are then accessible anywhere. Something like:
B4X:
Public Const FIELD1 As String = "Field1"
Public Const FIELD2 As String = "Field2"
Public Const FIELD3 As String = "Field3"
Public Const FIELD4 As String = "Field4"
 

Martin D.

Member
Licensed User
Thanks for the tip but I wish to use types so that if I change the name of the fields or add a couple in a row, I don't have to create/define a new const for each one of them.
 

stevel05

Expert
Licensed User
I don't think you will be able to change the fields defined in a class (which a type is under the hood) during program execution.
 

Martin D.

Member
Licensed User
So I should conclude that there is no JavaObject or Reflector trick that would allow me to set the value of a string field in a type ?
 

Jorge M A

Active Member
Licensed User
The following code is in B4J but it should be trivial to port it to B4A.
It's an adaptation of the code that was kindly provided to me by @Roycefer here^
B4J:
'Non-UI application (console / server application)
#Region Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True
#End Region

Sub Process_Globals
    Type BiomeType(t1 As String, t2 As String, t3 As String, t4 As String)
End Sub

Sub AppStart (Args() As String)
    Dim t As BiomeType
    t.Initialize
    t=TypeToType(t)
    Log(t)
End Sub

'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub

Sub TypeToType(o As Object) As Object
    Dim r As Reflector
    r.Target = o
    Dim jo As JavaObject = Me
    Dim fields() As String = jo.RunMethod("GetFields", Array(o))
    For Each f As String In fields
        If f="IsInitialized" Then Continue
        r.SetField(f,f,"java.lang.String")
    Next
    Return o
End Sub

#If JAVA
import java.lang.reflect.Field;
public static String[] GetFields(Object o)
{
    Class oc = o.getClass();
    Field[] fields = oc.getDeclaredFields();
    String[] res = new String[fields.length] ;
    for(int j=0;j<fields.length;j++)
    {
       res[j] = fields[j].getName();
    }
    return res;
}
#End If
 

Martin D.

Member
Licensed User
Very nice ! Exactly what I wanted. Thanks a lot !
What if I wanted to also get the fields of a code module ?
 
Top