In ActiveRecord, there's a concept of locking records for updates to ensure that a stale object doesn't get saved to the database.
Is there equivalent functionality in ActiveAndroid? If so, is there a link showing how to do it? If not, what would be the best approach to prevent stale objects from getting saved to the db?
ActiveAndroid has a concept of beginTransaction() and endTransaction() which basically are similar to the locking record concept in activeRecord. By using the beginTransaction() you ensure that while any changes being made to a method or data is being accessed, no other object can interfere with the process. Once the endTransaction() is executed, the method is "unlocked" and other objects can start to interact with it.
I don't know the answer, but what I am doing is, declaring an unique field in my model class, and onUniqueConflict replacing the old record with the new one.
#Column(name = "userId", notNull = true,unique = true,onUniqueConflict = Column.ConflictAction.REPLACE)
private String userId;
Related
maybe the headline does not fit the question really well so I'll explain it.
In my app I send a request to a server to get gerneral user information. If I receive on I want to save it into the local room db. Now we come to the problem. I want to bind this one user to the view directly out of the db. But I can not bind a element, which maybe does not exists, because the request is in progress.
(My bad solution): Creating another livedate element which holds a boolean. I create a observer in the Activity and add the observer after the boolean observes a "true". With this solution I can not use "Data Binding" in the xml layout.
Does anyone have an idea? (If you need further information just ask - I know it is a really abstract question without any code)
As Sanlok Lee mentioned:
If you reassign user then it becomes a completely different instance and the observer will not listen to the new LiveData. Instead you can do val user: MediatorLiveData<User> and later you can call user.addSource(dao.getUserById(1), ...)
OR:
Just load the user (also if you know that there is no one in the DB) from the DB. You can do that in you UserRepository for example.
val user: LiveData<User> = userDao.getUser()
The Livedata will get notified when there is a valid user inserted.
I've a simple data that i want to persist on firebase.
This data is a domain class for my relational model (i started with a relational model and now im deciding whenever or not migrate to firebase, but for awhile im working with both... or trying to)
To persist a new instance if my class on firebase i need to do:
Map<String, Object> firebase = new HashMap<String, Object>();
firebase.put("raffleDate", this.giveaway.getRaffleDate());
firebase.put("thumbnailUrl", this.giveaway.getThumbnailUrl());
firebase.put("mustFollowList", this.giveaway.getMustFollowList());
firebase.put("owner", this.giveaway.getOwner());
firebase.put("amountFriendsToIndicate", this.giveaway.getAmountFriendsToIndicate());
firebase.put("mediaId", this.giveaway.getMediaId());
((App) getApplication()).getFirebase().child("giveaways").child(this.giveaway.getMediaId()).setValue(firebase);
because besides these fields Giveaway has one last other field which has a circular reference to itself
#ToMany(referencedJoinProperty = "raffle")
#Expose(deserialize = false, serialize = false)
private List<UserOnGiveaway> attendantsTickets;
This field maps the relatioship between user and its giveaways, UserOnGiveaway class has a reference to User and Giveaway so when i try to persist i get a very long non compreensive error that I can just guess is due some stackoverflow because of the circular reference
The thing is I DONT REALLY CARE ABOUT PERSISTING THIS FIELD, in my actual "hybrid" archtecture i'm using firebase only to persist data shared among users, individual user data is being stored locally on android sqlite
So i would like to know is there any way i can annotate this field to force firebase ignore it?
or is there any parameter is can set on firebase call to do it?
PLEASE do not suggest transient as it will also affect my ORM
PLEASE2 do not suggest changes on domain since i'm giving a try to firebase i wont make any structural changes before decide for it.
thanks
You can use the #Exclude annotation on a field or getter/setter method to omit it from serialization with the Firebase SDK.
In Realm there are three methods isValid(), isLoaded(), isManaged().
I want to know which method should used when?
isValid
public final boolean isValid()
Checks if the RealmObject is still valid to use i.e., the RealmObject hasn't been deleted nor has the Realm been closed. It will always return true for unmanaged objects.
Two things invalidate a RealmObject:
- closing the Realm instance it belongs to
and deleting the object on any thread (if you're on an auto-updating
looper thread)
isLoaded
public final boolean isLoaded()
Checks if the query used to find this RealmObject has completed.
Async methods like RealmQuery.findFirstAsync() return an RealmObject that represents the future result of the RealmQuery. It can be considered similar to a Future in this regard.
Once isLoaded() returns true, the object represents the query result even if the query didn't find any object matching the query parameters. In this case the RealmObject will become a "null" object.
isManaged
public static boolean isManaged(E object)
Checks if this object is managed by Realm. A managed object is just a wrapper around the data in the underlying Realm file. On Looper threads, a managed object will be live-updated so it always points to the latest data. It is possible to register a change listener using addChangeListener(RealmModel, RealmChangeListener) to be notified when changes happen. Managed objects are thread confined so that they cannot be accessed from other threads than the one that created them.
Instances of Realm objects can be either managed or unmanaged.
Managed objects are persisted in Realm, are always up to date and thread confined. They are generally more lightweight than the unmanaged version as they take up less space on the Java heap.
Unmanaged objects are just like ordinary Java objects, they are not persisted and they will not be updated automatically. They can be moved freely across threads.
More info refer:https://realm.io/docs/java/4.3.3/api/io/realm/RealmObject.html
FROM DOCS
isValid()
Checks if the RealmObject is still valid to use i.e., the RealmObject hasn't been deleted nor has the Realm been closed. It will always return true for unmanaged objects.
Note that this can be used to check the validity of certain conditions such as being null when observed.
EXAMPLE :
// With RealmObject
yourRealmObject.isValid();
isLoaded()
Checks if the query used to find this RealmObject has completed.
Returns:
true if the query has completed, false if the query is in progress.
3.
isManaged()
Checks if this object is managed by Realm. A managed object is just a wrapper around the data in the underlying Realm file. On Looper threads, a managed object will be live-updated so it always points to the latest data. It is possible to register a change listener using addChangeListener(RealmModel, RealmChangeListener) to be notified when changes happen. Managed objects are thread confined so that they cannot be accessed from other threads than the one that created them.
If this method returns false, the object is unmanaged. An unmanaged object is just a normal Java object, so it can be parsed freely across threads, but the data in the object is not connected to the underlying Realm, so it will not be live updated.
THE SCENARIO
I have a class that makes use of a request list set by the user. The request list is stored in SharedPreferences. The dilemma I'm facing is to whether to keep an instance of the request list or to read from SharedPreferences every time the request list is needed (which is very frequent).
Also not that Gson is used to deserialize the object.
The code goes like this:
public List<PrayerTimesCalculator.Time> getDefaultRequestList() {
if (mRequestList != null) return mRequestList;
// Try getting request list from preferences;
Gson gson = new Gson();
String json = mSharedPref.getString(KEY_PREF_REQUEST_LIST, null);
Type listType = new TypeToken<List<Time>>() {
}.getType();
mRequestList = gson.fromJson(json, listType);
if (mRequestList != null) return mRequestList;
// Create default list;
mRequestList = Arrays.asList(
Time.DAWN,
Time.MORNING,
Time.AFTERNOON,
Time.EVENING,
Time.MID_NIGHT);
return mRequestList;
}
THE GOAL
My concern is that if I keep around an instance of the request list, and there are multiple instances of this class, an update to the request list in one instance of the class would not be reflected in the rest of the instances until they are recreated.
Thus, I'm leaning towards reading from SharedPreferences unless there is a better way to keep the request list objected updated in all instances.
THE QUESTION
(1) So, how efficient is it to read the same key from SharedPreferences quite frequently by multiple instances of the object? and (2) Is there a better way to keep the request list objected updated in all instances?
So there are a couple of approaches you can take to this.
First, your object is small - re-reading SharedPreferences thousands of times would hardly be noticeable. It's not like SharedPreferences is on a remote drive or has a "bad connection."
Second, if you don't like that answer, then you need a DAO (Data Access Object). SharedPreferences is a form of this already. It provides a means to store and retrieve data with confidence that you have the most recent data available. But, if you feel like you can improve on it's optimization (because it's generic, and this is your app), then you can provide access to you data through a static object that performs both "read" and "write" operations. This will guarantee that access to the object is done with the most recent data. Of course, you will need to be thread aware, etc. (something that is not always guaranteed by SharedPreferences).
Next, you could persist your data in a database and use Cursors or other built-in or custom DAOs. This requires another level of complexity and a lot of overhead, but is useful when several components of your app might need access to the data, provide updates or needs real-time monitoring of changes because background threads or other objects may make modifications that will change your app behavior or result in UI updates.
Last, you could use more complex data stores like a Content Provider. This is really required for cases where you want/need other apps to access data provided by your app (and your app may also consume the data). That's a complex solution and implementation is well outside the scope of this question.
But I mention it because you seem interested in being certain that frequent reads of SharedPreferences is acceptable. It definitely is acceptable - otherwise there would be something else besides it, databases and Content Providers.
I'm using greendao for a android project and wanted to know how to properly delete and object from the db and from the session cache. Currently I do the following to delete from the db:
ChatDao chatDao = daoSession.getChatDao();
chatDao.queryBuilder().buildDelete().executeDeleteWithoutDetachingEntities();
However as the method name and documentation state this may leave stale objects in the session cache, how can I remove the objects from there too?
In order to clear cached objects in your DaoSession use this call:
DaoSession.clear();
It will clear all objects in your session identity scope.
As Anatoliy described, you can use DaoSession.clear(). However, it will clear all all objects from the session. If you want to avoid that, you have to execute a regular query and delete the result entities (for example with deleteInTx).