public class ChallengeDB extends RealmObject {
#PrimaryKey
private int challengeId;
private String targetType;
private RealmList<ChallengeTargetDB> ChallengeTargetDB;
private boolean isTargetPerParticipant;
}
public class ChallengeTargetDB extends RealmObject {
#PrimaryKey
private int targetId;
private String targetName;
private String description;
private long targetValue;
private int targetStep;
private boolean isPassed;
}
I have these 2 tables linked as following and I need to get max "targetValue" value of a specific challengeId.
The query for which I have written is as follows
RealmResults<ChallengeDB> challengeDBs = realm.where(ChallengeDB.class)
.equalTo(WorkoutCashConstants.COLUMN_CHALLENGE_ID, challengeDB.getChallengeId()).findAll();
long max = challengeDBs.max("ChallengeTargetDB.targetValue").longValue();
I get up ending exception as follows
java.lang.IllegalArgumentException: Aggregates on child object fields are not supported: ChallengeTargetDB.targetValue
With Realm 3.5.0+
public class ChallengeTargetDB extends RealmObject {
#PrimaryKey
private int targetId;
private String targetName;
private String description;
private long targetValue;
private int targetStep;
private boolean isPassed;
#LinkingObjects("ChallengeTargetDb")
private final RealmResults<ChallengeDb> targetOfChallenge = null;
}
Then
RealmResults<ChallengeTargetDB> challengeDBs = realm.where(ChallengeTargetDB.class)
.equalTo("targetOfChallenge." + WorkoutCashConstants.COLUMN_CHALLENGE_ID, challengeDB.getChallengeId()).findAll();
long max = challengeDBs.max("targetValue").longValue();
As the exception says, aggregates on linked object's field are not supported. You need to compute it by yourself.
Try this:
Number max = null;
for (ChallengeDB item : challengeDBs) {
if (max == null) {
max = item.ChallengeTargetDB.max();
} else {
Number tmp = item.ChallengeTargetDB.max();
max = max.longValue() > tmp.longValue() ? max : tmp;
}
}
Related
It's rather, a question than a problem. I have two entities with a String field called Type. Both have over twenty kinds of type: "Bills", "Transport", "Awards" etc. I want to put all them to the charts, and this is creating little problem because it totally creates over 60((!) 60 because I want to take data by date. For example day, month etc.)instances in ViewModel constructor and over 60 observers in fragment. So my question is:
There is some problem to make it more sexy for code (orderliness), performance of app, or I should not care about it?
One of entity (they are almost same):
#Entity(tableName = "expense_table")
public class Expense {
#PrimaryKey(autoGenerate = true)
private int expenseId;
private String note;
private Double value;
private String type;
private Long dateLong = System.currentTimeMillis();
private String date = new SimpleDateFormat("MM/yyyy").format(new Date(dateLong));
private static Calendar cal = Calendar.getInstance();
private int month = cal.get(Calendar.MONTH) + 1;
private int day = cal.get(Calendar.DAY_OF_MONTH);
private int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
private String weekDay = new DateFormatSymbols().getWeekdays()[dayOfWeek];
Query in Dao:
#Query("SELECT SUM(value) FROM expense_table WHERE type = :type")
MutableLiveData<List<Double>> getTotalType(String type);
One of Repository(As you can see there is many instances now, co code it will more complicated):
public class ExpenseRepository {
private ExpenseDao expenseDao;
private LiveData<List<Expense>> allExpensesDay;
private LiveData<List<Expense>> allExpensesMonth;
private LiveData<List<Expense>> allExpenses;
private LiveData<Double> totalValue;
private LiveData<Double> totalValueDay;
private LiveData<Double> totalValueMonth;
private MutableLiveData<List<Double>> totalType;
private String type = "Bills";
public ExpenseRepository(Application application) {
ExpenseIncomeDatabase database = ExpenseIncomeDatabase.getInstance(application);
expenseDao = database.expenseDao();
allExpenses = expenseDao.getAllExpenses();
allExpensesDay = expenseDao.getExpensesDay();
allExpensesMonth = expenseDao.getExpensesMonth();
totalValueDay = expenseDao.getTotalValueDay();
totalValueMonth = expenseDao.getTotalValueMonth();
totalValue = expenseDao.getTotalValue();
totalType = expenseDao.getTotalType(type);
One of Repository:
private LiveData<Double> totalExpenseValue;
private LiveData<Double> totalIncomeValue;
private MutableLiveData<List<Double>> totalType;
public TotalStatsViewModel(#NonNull Application application) {
super(application);
ExpenseRepository expenseRepository = new ExpenseRepository(application);
ExpenseRepository expenseChartsRepository = new ExpenseRepository(application);
IncomeRepository incomeRepository = new IncomeRepository(application);
totalExpenseValue = expenseChartsRepository.getTotalValue();
totalIncomeValue = incomeRepository.getTotalValue();
totalType = expenseRepository.getTotalType();
}
public LiveData<Double> getTotalExpenseValue() {
return totalExpenseValue;
}
public LiveData<Double> getTotalIncomeValue() {
return totalIncomeValue;
}
public LiveData<List<Double>> getTotalType() {
return totalType;
}
As you can see there is a lot of code now. In future it will be much more. Maybe it stupid question, but I just care about orderliness and performance.
In an android project i have a class with these fields:
public class TransactionHistoryDetail1 implements Parcelable, DatabaseEnabled{
private long id;
private static final String TABLE_NAME = "TransactionHistoryDetail";
private static final String EMPTY_STRING = "";
#XmlElement(name = "TxUd", required = true)
private String TxUd;
#XmlElement(name = "TxLclDtTm", required = true)
private Date TxLclDtTm;
#XmlElement(name = "CcyCd")
private CurrencyCode CcyCd;
#XmlElement(name = "Amt")
private BigDecimal Amt;
#XmlElement(name = "PmttpCd", required = true)
private PaymentTypeCode PmttpCd;
#XmlElement(name = "OprtnCd", required = true)
private OperationCode OprtnCd;
#XmlElement(name = "AppLabltpCd", required = true)
private AppLabelTypeCode AppLabltpCd;
#XmlElement(name = "PdSrl")
private String PdSrl;
#XmlElement(name = "PdBrndDsc")
private String PdBrndDsc;
#XmlElement(name = "UsrEml")
private String UsrEml;
#XmlElement(name = "CstmrAdr")
private String CstmrAdr;
#XmlElement(name = "TxDtlDsc")
private String TxDtlDsc;
#XmlElement(name = "TxRltdInd")
private boolean TxRltdInd;
#XmlElement(name = "TxSttsCd", required = true)
private TransactionStatusCode TxSttsCd;
#XmlElement(name = "UpdtDt", required = true)
private Date UpdtDt;
...
}
Im trying to Write and Read objects of this class as Parcelables but im not sure how to write and read the enums.
My writeToParcel method looks like this:
#Override
public void writeToParcel(Parcel dest, int flags) {
SimpleDateFormat sdf = new SimpleDateFormat(JsonBuilder.DateFormat);
dest.writeLong(id);
dest.writeDouble(Amt.doubleValue());
dest.writeString(PdSrl);
dest.writeString(PdBrndDsc);
dest.writeString(TxUd);
dest.writeString(PdSrl);
dest.writeString(UsrEml);
dest.writeString(CstmrAdr);
dest.writeString(TxDtlDsc);
dest.writeString((CcyCd == null) ? "" : CcyCd.name());
dest.writeString((PmttpCd == null) ? "" : PmttpCd.name());
dest.writeString((OprtnCd == null) ? "" : OprtnCd.name());
dest.writeString((AppLabltpCd == null) ? "" : AppLabltpCd.name());
dest.writeString(sdf.format(TxLclDtTm));
dest.writeString(sdf.format(UpdtDt));
dest.writeByte((byte) (TxRltdInd ? 1 : 0));
}
and my Constructor with Parcel looks like this
private TransactionHistoryDetail1(Parcel in) {
SimpleDateFormat sdf = new SimpleDateFormat(JsonBuilder.DateFormat);
try {
TxLclDtTm = sdf.parse(in.readString());
UpdtDt = sdf.parse(in.readString());
} catch (ParseException e) {
e.printStackTrace();
}
id = in.readLong();
TxUd = in.readString();
PdSrl = in.readString();
PdBrndDsc = in.readString();
UsrEml = in.readString();
CstmrAdr = in.readString();
TxDtlDsc = in.readString();
TxRltdInd = in.readByte() != 0;
Amt = new BigDecimal(in.readDouble());
CcyCd = CurrencyCode.valueOf(in.readString());
PmttpCd = PaymentTypeCode.valueOf(in.readString());
OprtnCd = OperationCode.valueOf(in.readString());
AppLabltpCd = AppLabelTypeCode.valueOf(in.readString());
TxSttsCd = TransactionStatusCode.fromValue(in.readString());
}
The writeToParcel i belive its working well, but the constructor is crashing at the "CcyCd" line.
My CurrencyCode class is a enum, (so are PaymentTypeCode,OperationCode and AppLabelTypeCode) that looks like this:
#XmlType(name = "CurrencyCode")
#XmlEnum
public enum CurrencyCode {
EUR;
public String value() {
return name();
}
public static CurrencyCode fromValue(String v) {
return valueOf(v);
}
}
Is there another way to deal with enums in Parcelables?
The exception i get is this:
java.lang.RuntimeException: Unable to start activity ComponentInfo{package/package.activities.ChildActivity}: java.lang.IllegalArgumentException: No enum constant package.data.apiClasses.CurrencyCode.��EUR����CASH������CLS����APP����2017-04-10T09:07:52.525Z������2017-04-10T09:07:52.528Z����������CHILD_12345������?
First of all you should read from the Parcel in the exact order that you wrote to it. Since Parcel just write and read data in order instead of actually serializing data you have to keep read and write in order else you gonna read wrong values and getting error..
It is the best if you treat Enum as int, write them to parcel like this:
dest.writeInt(this.CcyCd == null ? -1 : this.CurrencyCode.ordinal());
and read them like this:
int tmpCurrencyCode = in.readInt();
this.CcyCd = tmpCurrencyCode == -1 ? null : CurrencyCode.values()[tmpMState];
P.S: This code check for null values too ^^
I had problem parsing Nullable Enum. If this is your case, look up here
https://stackoverflow.com/a/58337932/5980046
I have a problem with Realm that ill my brain :(
The problem is when I try to add a new object into RealmList. The object is inserted but it is not linked with the relationship.
Now, my database has multiple relationships:
User 1-->M Trip 1-->M Vehicle 1-->M
And then:
Vehicle 1-->M VehicleInfo
VehicleInfo 1-->M Temperature
The problem reside when I try to insert a new object into Temperature class.
My classes:
Vehicle:
#RealmClass
public class Vehicle extends RealmObject
{
private String state; //R: Reservado | P: Listo para embarcar | E: Embarcado | P1: Pdte. confirmar medidas | P2: Tª no válida | R1: No embarca
private String locata = "";
private String customer = "";
private String customerCode = "";
private String originPort = ""; //Origin port
private String destinyPort = ""; //Destiny port
private int fp; //Method pay (0 = CASH | 1 = CREDIT)
//Relationship
private Trip trip; //Inverse
private RealmList<VehicleInfo> vehicleInfo = new RealmList<>(); //One-to-many
private RealmList<Observation> observations = new RealmList<>();; //One-to-many
.....
}
VehicleInfo:
#RealmClass
public class VehicleInfo extends RealmObject {
private String sv; //Vehicle type
private String licensePlate = ""; //License
private String seal = ""; //Seal
private String temperature = ""; //Temperature control
private String iv = ""; //Ida/Vuelta
private String commodityCode = "";
private int tara = 0; //TARA
private int packages = 0; //Bultos
private int weight = 0;
private double length = 0.0; //Meters
private boolean flagFT; //Flag Technical data
private boolean flagDua;
private boolean flagManifest;
private boolean flagTransport;
private boolean flagDangerCommodity;
//Relationship
private RealmList<Temperature> temperatures = new RealmList<>(); //One-to-many
....
}
My code to add new Temperature:
Temperature temp = new Temperature();
temp.setDate(appCommon.getCurrentTimeOrDate("DATE"));
temp.setTime(appCommon.getCurrentTimeOrDate("TIME"));
temp.setValue(Double.parseDouble(etTemp.getText().toString()));
VehicleInfoPersistence.updateVehicleInfoTemperature(realm, vehicle.getLocata(), selectedUnitPosition, temp);
updateRecycler(tempRecyclerAdapter, temp);
Method to find and persist in Realm:
public static VehicleInfo findVehicleInfoFromLocata(Realm realm, String locata, int position) {
RealmQuery<Vehicle> query = realm.where(Vehicle.class).equalTo("locata", locata);
Vehicle realmVehicle = query.findFirst();
return realmVehicle.getVehicleInfo().get(position);
}
public static void updateVehicleInfoTemperature(Realm realm, String locata, int position, Temperature temperature) {
Vehicle vehicle = VehiclePersistence.findVehicleFromLocata(realm, locata);
realm.beginTransaction();
Temperature realmTemp = realm.copyToRealm(temperature);
vehicle.getVehicleInfo().get(position).getTemperatures().add(realmTemp);
realm.commitTransaction();
}
How I said, object is created in database but it is not linked with the vehicle-->vehicleInfo-->Temperature.
What's wrong in my code??
Thanks in advance :)
I resolved my problem :)
By some motive, realm fails when I try to add new object into sub-array of a RealmClass.
To solve this issue I've created an intermediate object and then I've added the object to this intermediate object.
public static void updateVehicleInfoTemperature(Realm realm, String locata, int position, Temperature temperature) {
Vehicle vehicle = VehiclePersistence.findVehicleFromLocata(realm, locata);
realm.beginTransaction();
VehicleInfo vInfo = vehicle.getVehicleInfo().get(position);
VehicleInfo realmVehicleInfo = realm.copyToRealm(vInfo);
Temperature realmTemp = realm.copyToRealm(temperature);
realmVehicleInfo.getTemperatures().add(realmTemp);
realm.commitTransaction();
}
I hope to help someone :)
My requirement is get state of all same async class call same time in loop.
for (int i = 0; i < numberOfTasks; i++) {
int taskId = i + 1;
startTask(taskId, taskDuration, useParallelExecution);
}
private void startTask(int taskId, int taskDuration, boolean useParallelExecution) {
TestTask task = new TestTask(taskId, taskDuration);
if (useParallelExecution) {
// this type of executor uses the following params:
//
// private static final int CORE_POOL_SIZE = 5;
// private static final int MAXIMUM_POOL_SIZE = 128;
// private static final int KEEP_ALIVE = 1;
//
// private static final ThreadFactory sThreadFactory = new ThreadFactory() {
// private final AtomicInteger mCount = new AtomicInteger(1);
//
// public Thread newThread(Runnable r) {
// return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
// }
// };
//
// private static final BlockingQueue<Runnable> sPoolWorkQueue =
// new LinkedBlockingQueue<Runnable>(10);
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
// this is the same as calling task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
task.execute();
}
}
private class TestTask extends AsyncTask<Void, Void, Void> /* Params, Progress, Result */ {
private final int id;
private final int duration;
TestTask(int id, int duration) {
this.id = id;
this.duration = duration;
}
#Override
protected Void doInBackground(Void... params) {
int taskExecutionNumber = executedTasksCount.incrementAndGet();
log("doInBackground: entered, taskExecutionNumber = " + taskExecutionNumber);
SystemClock.sleep(duration); // emulates some job
log("doInBackground: is about to finish, taskExecutionNumber = " + taskExecutionNumber);
return null;
}
private void log(String msg) {
Log.d("TestTask #" + id, msg);
}
}
Here i have to get state for all TestTask async class call simultaneously. I have done lots of R&D on it but not getting any solution. Anybody know how to get state of same async class call simultaneously then help me.
Thank you in advance.
Here is solution.
First you have to save TestTask.class's instance into some list. For that use HashMap<Integer,TestTask> because it could be better when you want to check asynctask's status by id.
Now you can have list of your asyncTasks so just create for loop and check status by getting tasks from your position count of loop.
One other hint, If you want to check status when Activity is finished just save this hashMap and retrieve it when you need to check task's status.
This is my JSON string:
[{"BranchID":1,"SecurityCode1":13,"SecurityCode2":14,"PrintHeight":10,"PrintWidth":10,"Active":true}]
This is Code I am using to parse the JSON:
Type t = new TypeToken<List<Setting>>() {
}.getClass();
String json = ServiceHelper.getJSON(response);
List<Setting> list = (List<Setting>) gson.fromJson(json, t);
//list is null which it souldnt
This is the Setting class, Entity is ORMDroid entity class:
public class Setting extends Entity {
#Column(name = "id", primaryKey = true)
#SerializedName("BranchID")
public int BranchID;
public int securityCodeLPK;
public int securityCodeSDK;
#SerializedName("PrintHeight")
public int PrintHeight;
#SerializedName("PrintWidth")
public int PrintWidth;
#SerializedName("Active")
public String Active;
#SerializedName("SecurityCode1")
public String SecurityCode1;
#SerializedName("SecurityCode2")
public String SecurityCode2;
public Setting(int BranchID, int height, int width, String active, String securityCode1, String securityCode2) {
super();
BranchID = BranchID;
PrintHeight = height;
PrintWidth = width;
Active = active;
SecurityCode1 = securityCode1;
SecurityCode2 = securityCode2;
}
public Setting () {
super();
}
}
It seems to be OK, but list after gson.FromJson is null. What's wrong with this code?
Please help
You should use getType() instead of getClass().
Type t = new TypeToken<List<Setting>>() {}.getType();