Getting started with sugarORM 1.4 - android

I'm trying to figure out how to use sugarORM (version 1.4, imported with Gradle).
I have a simple object with a public String name field, among others.
I construct that simple object with that name and save it like this (with TEST_TYPE a random String) :
CustomObject type = new CustomObject(TEST_TYPE);
long l=type.save();
Toast.makeText(this, "Type ajouté ! id="+l, Toast.LENGTH_SHORT).show();
My log is showing id=14 by now, so I assume writing is OK.
But when I want to read, there is no sense :
CustomObject.count(CustomObject.class) returns 14
CustomObject.findById(CustomObject.class, 2) returns null
CustomObject.first(CustomObject.class) returns null
CustomObject.find(LifeEventType.class, "NAME = ?", new String[]{TEST_TYPE}) returns null
I don't know if it is related, but I get this exception on warning log :
java.lang.NoSuchMethodException: <init> at com.orm.SugarRecord.find(SugarRecord.java:196) (which is code too advanced for a noob like me...)
What am I doing wrong ?

It happens when you don't provide an empty contructor.
SugarORM can correctly save the entities, but can't instantiate them when you try to perform a select query.
The solution is to include an empty constructor and the getters/setters within your entity
public CustomObject(){}
More documentation here

Related

What does the single exclamation "!" mean after the type in Kotlin?

I'm learning to Develop Android Apps using Kotlin. I previously used to Develop using Java. While coding in Android Studio, I can see that the return types, parameters, etc. used in the Lambdas, methods, etc. are written as View!.
I know that the ? after the type in Kotlin means a Nullable type. Though what does the ! mean.
For example:
val item = mySpinner.selectedItem
The return type is Any! What does the ! mean? Is it the same as a Nullable type i.e. Any? ?
Thanks.
It's a platform type indicating that Kotlin is not sure whether it will be null or not null, it's like saying "maybe".
platform types can't be mentioned explicitly in the program, so there's no syntax for them in the language. Nevertheless, the compiler and IDE need to display them sometimes (for example, in error messages or parameter info), so there is a mnemonic notation for them:
T! means "T or T?",
(Mutable)Collection! means "Java collection of T may be mutable or not, may be nullable or not",
Array<(out) T>! means "Java array of T (or a subtype of T), nullable or not"
And because it can either be null or not null, it is up to you how you will treat it.
Also check this another post

How to rename realm object in iOS

I am using realm in our iOS and Android app. For some reason i want to rename one of my realm object.
Initially we name the object Demo and now I want to change it to RealmDemo
In android we achieved it by using #RealmClass annotation
#RealmClass(name = "Demo")
open class RealmDemo : RealmObject() {
}
On iOS side i am not sure how exactly i can do similar as i did in android.
class RealmDemo: Object {
override static func className() -> String {
"Demo"
}
}
I tried above ^ but getting following error "Terminating app due to uncaught exception 'RLMException', reason: 'Object type 'Demo' not managed by the Realm'"
Two things.
First, You can name an object anything you want and change its name at any time.
HOWEVER, that's a destructive change, and Realm doesn't have any way to know the the newly named object 'is the same object' as the prior object.
How that's handled depends on what the use case is:
If this is a development situation, delete your local Realm files and run the app and the object with the new name will be created automatically.
If this is production then a migration block is needed (as on any platform) to migrate the data from the old object to the new one.
Secondly, The other important thing is the name of the object is now RealmDemo, whereas the prior object is Demo
class RealmDemo: Object {
so technically those are two separate objects. To Realm, you've abandoned the Demo object totally and that's a destructive change. Demo is still hanging around but is not referenced in your code so an error is thrown
On a possibly unrelated note, the className function references Demo
override static func className() -> String {
"Demo"
}
But the object name is RealmDemo.
It's not clear why the className function exists but it's not required or really needed. See the documentation for objects to get a feel for their structure - they may need a Primary Key
Seems like realm does not support className overriding for cocoa/ios.
https://github.com/realm/realm-cocoa/issues/2194
https://github.com/realm/realm-cocoa/issues/6624

Firebase fetching data as Kotlin data type Any

I am trying to fetch an entire node in one shot from Firebase Real-time database as type Any. The code that I use is as follows:
val offerDetails = p0.child(querykey).child("Offers").child(offerkey).getValue(Any::class.java)
Log.d("MyMessage",
offerDetails.toString())
The data is obtained perfectly as the Log returns:
{offer=90, ****ID=********, deliveryHour=0, mobile=******, type=2, deliveryMinute=15, offerComment=******}
However, I am unable to fetch the individual data like the offer, type, etc hereon. Can someone help me out?
P.S. I can get each of the datapoints individually from Firebase. But I am trying to avoid that and instead get the entire node in one shot.
When you are using the following line of code:
val offerDetails = p0.child(querykey).child("Offers").child(offerkey).getValue(Any::class.java)
The type of the object is Any and not Offer, so you can access its properties. When you are using:
Log.d("MyMessage", offerDetails.toString())
You are just printing in the logcat the String representation of your offerDetails object. If you need to access its properties, then you should cast that object to an object of type Offer.
Log.d("MyMessage", (offerDetails as Offer).offer)
In this way, you are telling the compiler that the object is of type Offer and not Any. In this case, the output in the logcat will be:
90
Edit:
You can also access the properties using the following line of code:
val offer = p0.child(querykey).child("Offers").child(offerkey).child("offer").getValue(String::class.java)
Log.d("MyMessage", offer)
Same output (90) in the logcat.
Firebase Supported Data Types
Your object is most likely returning as a Map<String, Object> object. Maybe use the map as you can read/write it better than an Any object

What is mId in activeandroid and when can it be null?

I am creating and trying to save a table using active android but for some reason the object fails to save. The error that I get is
java.lang.NullPointerException: Attempt to invoke virtual method 'long java.lang.Long.longValue()' on a null object reference
Upon debugging the decompiled Model.class file I observed that an exception occurs while executing the following statement
(Please note that the below line is from the decompiled Model.class file of activeandroid)
long entityId1 = ((Model)e).getId().longValue();
It fails and the above said exception occurs. In the catch block I observe that for all non-primitive type fields the mId is non null, but for the field where the exception occurs the mId is null. I tried to search the web but could only find one line about mId.
ActiveAndroid automatically creates another auto-increment ID column. This is mId.
Then why does it fail to do so in this case. Does somebody have an idea? Thanks !!
OK I found the answer.
From codepath I found that
The problem is that This is because ActiveAndroid needs you to save
all objects separately. Before saving a tweet for example, be sure to
save the associated user object first. So when you have a tweet that
references a user be sure to user.save() before you call tweet.save()
since storing the user requires the local id to be set and assigned as
the foreign key for the tweet.
Thus I had to save my non primitive type object field first before saving the object.

Android ORMLite 4.38 allowGeneratedIdInsert causing IllegalStateException

I'm targeting Android 2.2 and newer. This error was generated on a device running 4.x. I am using ORMLite 4.38 libraries.
I need to guarantee every record instance is unique for any number of devices. I was happy to see that ORMLite supports UUIDs as IDs. I've created a UUID - id abstract base class for my database record definitions. allowGeneratedIdInsert is the perfect solution. But this feature seems to cause an 'IllegalStateException: could not create data element in dao'. I tested by removing this annotation, and no issue. Put it back in...same issue. Put the base class stuff in one record definition...same issue.
LogCat also reports:
Caused by: java.sql.SQLException: Unable to run insert stmt on object - objectid: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx
public abstract class UUIDDaoEnabled<T> extends BaseDaoEnabled<T, UUID> {
//allowGeneratedIdInsert allows us to set UUID when this device db didn't create it
#DatabaseField(generatedId = true, allowGeneratedIdInsert=true)
private UUID id;
...
public void setUUIDFromSerializedSource(SerializedModelBinaryInputStream stream, Dao<T, UUID> dao) throws SQLException { //only place we can set UUIDs
if(id == null)
dao.refresh((T)this);
if(id != null)
throw new SQLException("Trying to set UUID on existing object");
id = stream.getCurrentUUID();
}
}
I'll specialize like so:
#DatabaseTable()
public class Type extends UUIDDaoEnabled<Type> { ... }
I can't explain this from the documentation for allowGeneratedIdInsert and generatedId. In fact the documentation for alloeGeneratedIdInsert says it overrides the default behavior of generatedId. It also says
This only works if the database supports this behavior
Yet, I have read in other posts that ORMLite 4.25 (?) and newer supports this behavior on Android devices. So, either that's not entirely true. Or I'm doing something stupid...anyone???
UPDATE: after thinking about it for a minute, I realized that neither allowGeneratedIdInsert support, nor inheritance can be the root cause, because I instantiate other objects based on the same abstract class. What I can't figure out is why one particular class is causing the issue. The only unique thing about the offending record type (compared to other types that create) is it is a many in a one to many, and it contains several to manies. Could these properties, combined with allowGenereatedIdInsert, be the root issue? Rather, I should ask, has anyone seen this issue in this circumstance?
UPDATE: nevermind the question. I can use updateId(...) instead of allowGeneratedIdInsert.
So I'm not sure about this but it looks to me that you are trying to insert an element twice into a table with the same UUID id. The exception is saying there is a constraints failure:
IllegalStateException: Could not create data element in dao
at BaseForeignCollection.add(BaseForeignCollection.java:57)
...
Caused by: SQLiteConstraintException: error code 19: constraint failed
If you call foreignCollection.add(...); it does the same thing as dao.create(...); -- and you can't do both of these with the same object. If you have an existing object that has already been created by the DAO and you want to associate it with another object, you should do something like:
// associate this object with another
existingObject.setForeignField(...);
// now update it in the db
existingObjectDao.update(existingObject);
You can't add it to the foreignField's foreign collection.
I had a similar problem. But it was caused by using create instead createOrUpdate to save the object.
It is also important to uninstall the application before changing this to ensure that the database has been removed and will not keep the old behavior.
Edit: createOrUpdate is very time expensive. It's better use just create with great amounts of data.
Edit 2:It is also bether to use a TransactionManager.callInTransaction.

Categories

Resources