Android getDeclaredFields value

Asked

Viewed 121 times

3

I’m doing some studies of android, I don’t know much of the subject because I’m starting now, I would like to create a simple mvc of CRUD, where I want to call model.save();

So I created the following structure:

Mainactivity.java

Produto produto1 = new Produto(this);
produto1.setId(1);
produto1.setNome("CELULAR");
produto1.setPreco(5.5);
produto1.Save();

Java product.

@DatabaseTable (tableName = "produtos") 
public class Produto extends BaseModel{

     @DatabaseField(columnName="id",    columnType="INTEGER", primaryKey=true)
     private int id;

     @DatabaseField(columnName="nome", columnType="VARCHAR")
     private String nome;

     @DatabaseField(columnName="preco", columnType="DOUBLE", columnSize="10,9")
     private Double preco;

     @DatabaseField(columnName="endereco", columnType="TEXT", columnSize="50", canBeNull=true, defaultValue="NULL", unique=true)
     private Double endereco;

     public int getId() {return id;}
     public void setId(int id) {this.id = id;}
     public String getNome() {return nome;}
     public void setNome(String nome) {this.nome = nome;}
     public Double getPreco() {return preco;}
     public void setPreco(Double preco) {this.preco = preco;}

     public Produto(Context context) {
         super(context);
     }  
}

Databasetable.java

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) //can use in method only.
public @interface DatabaseTable {
    String tableName();  
}

Databasefield.java.

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD) //can use in method only.
public @interface DatabaseField {
     String columnName() default "";  
     String columnType(); 
     String defaultValue() default "";
     String columnSize() default "";
     boolean canBeNull() default true; 
     boolean unique() default false; 
     boolean primaryKey() default false; 
     boolean autoIncrement() default false; 
}

Basemodel.java

public class BaseModel extends DBFactory<BaseModel> {
 public BaseModel(Context context) {
      super(context);
 }
}

Dbfactory.java

public class DBFactory<T> extends SQLiteOpenHelper {
    private static final String DB_NAME = "VendasDB";
    private static final int DATABASE_VERSION  = 1;
    private final Context myContext;
    private static DBFactory mInstance = null;
    private static SQLiteDatabase myWritableDb;

    private Class t;
    public void set(Class t) { this.t = t; }
    public Class get() { return t; }

    public DBFactory(Context pContext){         
        super(pContext, DB_NAME, null, DATABASE_VERSION);
        this.myContext = pContext;
        this.set((Class) this.getClass());    
        Log.v("CreateTableOnModel",CreateTableOnModel());
    }

    public String Save()
    {
        Log.v("DBFactory", "SAVE()");
        Class clazz = get();

        DatabaseTable annot = (DatabaseTable) clazz.getAnnotation(DatabaseTable.class);
        StringBuilder sb = new StringBuilder();

        if(!annot.tableName().equals(""))
        {
            Field[] fields = clazz.getDeclaredFields();
            Field idField = null;

            try {
               idField = clazz.getDeclaredField("id");      
               idField.setAccessible(true);
               Object b = idField.get(get().newInstance());
               Log.v("idField:", b.toString());
            } catch (Exception nsfe) {
               System.out.println(nsfe.toString());
            }


        }
    }
}

Error:

03-31 16:26:23.780: I/System.out(32048): java.lang.InstantiationException: can't instantiate class br.com.rlsystem.vendas.model.Produto; no empty constructor

1 answer

1


The error occurs because you are trying to create an instance without passing arguments in the constructor of a class (Produto) that has parameters:

public Produto(Context context) {
    super(context);
}  

There are two ways to solve the problem:

  1. Remove the constructor with arguments and set the dependency on one Setter.

  2. Recover a reference to the manufacturer and use the newInstance builder’s passing the necessary arguments.


Updating

The method get() class Field requires the instance of an object to retrieve the value of the attribute.

The problem in this case is that you are creating another empty object.

Like Produto stretches DBFactory indirectly, what you need is to make reference to the object itself, in this case:

Object b = idField.get(this);
  • So I don’t know if I’m doing it correctly to rescue the values that are set in mainActivity, because I did a search and saw the method ". get()", only that it expects an Object, as I am trying to access the class "Product" I tried passing "newInstance()", how would I pass the argument to that "newInstance()"? because I tried: Object b = idField.get(get(). newInstance(this.myContext); but it doesn’t even let me compile anymore, give me an error: The method newInstance() in the type Class is not applicable for the Arguments (Context)

  • @Caião Do as described in item 2 above. Click on the links to see more details. It will look something like: get().getConstructor(Context.class).newInstance(context).

  • It worked, I just have a problem, I’m losing the reference of the product model, the value is coming empty, I think I should pass the reference of it passing in the super, something like public Product(Context context) {super(context,this);} .

  • @Caião I answered that question. That’s not the problem. I think I now understand what you’re trying to do. I’ll edit the question to reflect that. Refresh this page in 5 minutes.

  • Thanks, that solved my problem!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.