I have a HTTP Server and Android app.
All data -> JSON format. For mapping used Gson.
ORM - ActiveAndroid.
The problem : I need something like an observer/notifier object, which can told me, that a row in database updated just now.
Something like this :
public void interface Observable<T> {
void onItemUpdated(T item);
}
So I looking a solution. I've read ActiveAndroid docs, but it doesn't get to me any result. Maybe i can mix something with ContentObserver or something like this?
How about to create a logging table where you can append a row for each update.
It has the insertion cost but select query is so fast. And also you can store update history of each record if you want or delete the log record if you are worry about performance.
you can create new field in your db which holds the updated date and time and after every operations in db you may query the db about the recent updates done to your db
You can accomplish this by implementing your own ContentObserver for the URI of the table you want to be notified about. ActiveAndroid has its own content provider you can use or you can implement your own, that works with your tables. In one of my projects I used ActiveAndroid and had my own content provider for 3rd party apps. Upon an update/insert/deletion of a row you should be notified by content provider that something was changed with reference to some URI and if you have a registered content observer to this URI you will be notified.
Related
I have an app already in production, and now I want to change database property names in several tables to reduce bandwidth.
For eg, realtime database existing property is:
purchasePrice: 60
and by using #PropertyName, I want to change it so it now looks like this:
pp: 60
The changed POJO now has #PropertyName like:
#PropertyName("pp")
public float purchasePrice;
The question is: What is the best migration strategy so that all existing 'purchasePrice' is updated to new name in the realtime database, i.e 'pp' in this example case?
One naive approach I can think of is, on app update at client end, pull all data using old POJOs and assign each property to new POJOs (newPOJO.pp = oldPOJO.purchasePrice) and then save it in DB. But there should be a better way, as I have many POJOs.
Thanks,
If you want to change the name of a field in the database everywhere it occurs, there is really no easy way to do this. You're going to have to:
Query all of the nodes where it could appear
Check to see if the field needs to change
Write the new data back to that location
Whether you do that with code that uses #PropertyName or something more generic, it doesn't really matter.
I'm implementing a Content Provider, which is backed by a fairly complex SQLite DB schema. The database has a few junction tables and I'm unsure whether they should be visible to the user of the Content Provider or not.
The parent tables are exposed via the Contract, each one has its own content URI, etc. Now, when inserting data via ContentResolver#applyBatch() method, I create ContentProviderOperation per each table's content URI. So far everything is clear. But my problem is, how should the junction tables be populated, as they don't have their own content URIs?
To illustrate this, here's an example. I have 2 "parent" tables, Movies and Actors. The relationship between them is many-to-many and therefore I have a junction table called MoviesActors.
To insert at one batch I do the following:
List<ContentProviderOperation> operations = new ArrayList<>;
// movie
operations.add(ContentProviderOperation.newInsert(Contract.Movie.ContentUri).withValue("movie_id", "23asd2kwe0231123sa").build());
// actor
operations.add(ContentProviderOperation.newInsert(Contract.Actor.ContentUri).withValue("actor_id", "89asd02kjlwe081231a").build());
getContentResolver().applyBatch(authority, operations);
The junction table MoviesActors should be inserted with a row containing movie_id and actor_id. How do I take care of the junction table in this situation?
The only thing, which comes to my mind is extend the Contract to have content URI pointing to the junction tables and add another ContentProviderOperation, since otherwise, how do you communicate movie_id and actor_id to ContentProvider#applyBatch()?
I rather not expose the junction table to the user of the ContentProvider, but I might be wrong here... perhaps that's how it should be done on Android?
I've searched this topic for days already and haven't found an answer to that.
Any help would be greatly appreciated.
Bonus question:
Is it necessary to expose every single table via the Contract? For instance, when having child tables in one-to-many relationship. I'm specifically referring to Insert/Update/Delete since I know with Query I can simply do a join, but maybe I'm wrong also here.
Thanks a lot!
NOTE: I'm not interested in 3rd party library solutions.
I think you're tackling the problem from the wrong end. You're trying to design an interface to match your database structure, but the interface should come first.
In the first place, the interface should meet all the requirements of your ContentProvider client. If your ContentProvider client needs access to the junction table you'll have to expose it (in some way, see below), otherwise you don't have to. A good interface hides the actual implementation details, so the ContentProvider client doesn't need to care about whether the ContentProvider is backed by an SQLite database, by a bunch of in-memory maps or even a web-service.
Also, you should not think of a ContentProvider just as an interface to a database and the Contract as the database schema. A ContentProvider is much more versatile and powerful than that. The major difference is that ContentProviders are addressed by URIs whereas in SQL you just have table names. In contrast to a table name, a URI has a structure. URIs have a path that identifies the object (or directory of objects) that you want to operate on. Also you can add query parameters to a URI to modify the behavior of an operation. In this respect a ContentProvider can be designed much like a RESTful service.
See below for a concrete (but incomplete) example of a Contract of a simple movie database. This is basically how one would design a RESTful web-service, except for one thing: Just like in your code, movie-id and actor-id are provided by the caller. A real RESTful service would create and assign these automatically and return them to the caller. A ContentProvider can only return long IDs when inserting new objects.
Insert a new movie
insert on /movies/
Values: {"movie_id": <movie-id>, "title": <movie-title>, "year": ...}
Insert a new actor
insert on /actors/
Values: {"actor_id": <actor-id>, "name": <actor-name>, "gender": ...}
Add an existing actor to a movie
insert on /movies/movie-id/actors/
Values: {"actor_id": <actor-id>}
Add an existing movie to an actor:
insert on /actors/actor-id/movies/
Values: {"movie_id": <movie-id>}
Optional: add a new actor directly to a movie:
insert on /movies/movie-id/actors/
Values: {"actor_id": <actor-id>, "name": <actor-name>, "gender": ... }
If no actor with the given id exists, this operation will create the new actor and link it to the movie in a single step. If an actor with this ID already exists an exception would be thrown.
The same could be done the other way round, adding a new movie to an actor.
Delete an actor from a movie
delete on /movies/movie-id/actors/actor-id
or
delete on /actors/actors-id/movies/movie-id
Get all movies
query on /movies/
Get a specific movie
query on /movies/movie-id
Get all actors playing in a specific movie
query on /movies/movie-id/actors/
Get all movies a specific actor has played in
query on /actors/actor-id/movies/
The optional query selection statement can be used to filter the result. To get movies from the last 10 years a specific actor has played in, you would add the selection movies_year>=2005 to the last query.
By using a contract like this you wouldn't expose the junction table, instead you provide a REST-like interface to your database.
The job of the ContentProvider is to map these operations onto the database or any other back-end.
I'm a new Android Developer and seem to have gotten in a little over my head. I am trying to make a listView update when I add more content to the list.
The ListView is based off of a SQLite database. I was able to get the ListView to be based on the SQLite database by making a ContentProvider for the SQLite database (which was suggested here). Now my issue is that I want to update the SQLite database and have it reflected on the ListView. I am using a loader and according to this if I implemented the loader right it will monitor the data.
I tried updating the SQLite database directly but, that didn't cause the ListView to update without closing and reopening. My instinct from there is that I should implement the insert method in my contentProvider. I did a very simple implementation:
#Override
public Uri insert(Uri uri, ContentValues contentValues) {
return ContentUris.withAppendedId(uri, mCollectionDB.insertCollection(contentValues));
}
Unfortunately, the result of this is my app crashes with a "java.lang.NullPointerException". This is especially confusing as using the exact same contentValues to make the .insertCollection call from my MainActivity works without issue.
The issue I'm really interested in is how to get my listView to update when I insert data into my SQLite database. If inserting into the ContentProvider is irrelevant then please ignore that. I'm not really sure where I went wrong so I'm not sure what other code may be useful, but I'm happy to edit in more code if it'll help.
You can check loader concept.
You can start with
http://www.vogella.com/articles/AndroidSQLite/article.html#todo
Following are other 2 good tutorials
http://mobile.tutsplus.com/tutorials/android/android-sdk_content-providers/
http://mobile.tutsplus.com/tutorials/android/android-sdk_loading-data_cursorloader/
Hey here is one example to insert data into sqlite database and display it in list view.
Have a look at it
The idea is simple insert data into database and on click of view button initialize List view with arraylist that contains data already inserted.
You can ask if you have any further queries.
I have a ContentProvider which handles all the data insertion and retrieval related to my application, I'm following the pattern suggested by Virgil Dobjanschi on Google I/O. I am using the first pattern.
My problem is that I have a logical entity that was represented by multiple tables in the database.
For example, I have an Articles table and an ArticleExtras table. Articles represents the article itself, while ArticleExtras represents addtional information about certain Article, like number of comments.
I used CursorAdapter in the UI to display the Article title and the number of comments of that Article in one row of ListView.
To implement that, I added a left outer join ArticleExtras on statement in my ContentProvider query method for Article table, in order for CursorAdapter to get ArticleExtras along with the Article itself.
When new Articles are fetched from the web, I insert it into the database via ContentProvider, and then the CursorAdapter got notified and update the UI, this part worked as expected.
But when I fetched the number of comments (ArticleExtras), I want the same CursorAdapter, which is watching for changes in the content://com.myapp.content/Articles, to be notified, too, so I can update my row in the ListView.
My current implementation is like this: After inserting ArticleExtras into the database, I start a new query to check if Articles table has any rows that is related to the ArticleExtras I just inserted. If so I'll make a new uri for that Article( for example: content://com.myapp.cotent/Articles/123), and call getContext().getContentResolver().notifyChange(uri, null), so the corresponding CursorAdapter that is watching for changes of this Article will get notified.
Is the approach correct, or is there any better way to implement what I want?
Checkout ContactsProvider2, in it they set the notification uri to the AUTHORITY_URI which appears to be a catch all for the other URIs in the provider. I had the same probem and I have tried this myself for a provider with multiple tables and joins on those tables, and it works fine.
I am using a ContentProvider for caching results from a web-service query. It is an HTTP request and the response content is XML. Most of the data is cached, so I simply query the DB, if not found, request from webservice, insert in DB and requery the DB. Thus the response is always a Cursor from SQLiteDatabaseHelper.
I have one result set that is not stored in the DB and since it is 100% transient, but I would like to provide the appearance of it coming from the DB's Cursor. Is there an easy way to do this? For example, if I could project it onto the cursor with a cursor.setValue("string", objectValue) or some other existing implementation.
If not, I will either bypass the DB for this content result, or stuff it into a trivial table that is constantly reused.
Depending on how you use it, it might not be too hard to write your own cursor class. For convenience, derive your class from AbstractCursor class which takes care of a lot of the details for you.
You may also be able to make use of MatrixCursor.