This is actually two questions:
If i expose my SQLite as a ContentProvider in my application it will work in an asynchronous fashion ?
Imagine i have the following tables in my database:
TableChats
TableChatMessages
and i also have a class
Message
To work with ListViews and have those list views use data from the ContentProvider must that data returned be a Cursor ? or is it possible to query for all messages in a chat and return an array of Message.
Sorry i know this may be a dumb question but i'm new to android development and the concept of ContentProvider and ListViews and how to connect them isn't quite yet clear to me.
To my knowledge
A content provider manages access to a central repository of data which shared between multiple applications. Normally all methods access the data work on the UI thread. If you want asynchronous, they suggest to use CursorLoader.
You can query all messages, get data from Cursor and put to your Message object.
Sample:
Cursor sampleCursor = getContentResolver().query("Your query");
ArrayList<Message> list;
if(sampleCursor!=null){
while(sampleCursor.moveNext()){
Message item = new Message();
item.sender = sampleCursor.getString(senderColumnIndex);
item.messageBody= sampleCursor.getString(messageBodyColumnIndex);
list.add(item);
}}
//Pass your list to your adapter.
Or directly pass your cursor using CursorAdapter
Related
I have a recyclerview which shows a list of students.
All of the students are held in a realmlist in the adapter.
When the user can ask for a data refresh, than the server sends the list of students back to the user.
What i am doing now is to download all of the information from the server , store it in the db , than retrieving it from the database(via realmresults) and than converting the realmresult to realmlist.
My question is how to properly update the UI?
I have seen in the documentation that realmlist have a managed mode where they are updating the ui automatically..
What is this managed mode? What does it means?
How do i use the realmlist to keep it in a managed state?
And what is the right way(aka best practice) to use realmlists?
Note that i cannot hold my information as realmresult directly because im performing some manipulation on the data that i dont want it to be saved.
Managed Object vs. Standalone
The standalone RealmObject/RealmList is created through the Object's constructor or the Realm.copyFromRealm() method. The data accessing in the standalone object won't go through the underline storage engine, instead, it behaves just like normal object. So the standalone object won't be refreshed when data changes. Examples for standalone object:
MyModel myModel = new MyModel(); // Standalone
MyModel model = realm.where(MyModel.class).findFirst(); // This is managed object.
MyModel standaloneModel = realm.copyFromRealm(model); // The returned value is standalone object.
MyList myList = new MyList(); // Standalone
The managed RealmObject/RealmList are accessing data though Realm's underlying storage engine. They are created when you do query from Realm, or the return from the copyToRealm() (and its variant methods). Like:
MyModel model = realm.where(MyModel.class).findFirst();
MyModel model = new MyModel(); // This is a standalone object.
model = realm.copyToRealm(modle); // The returned value is managed by Realm now.
MyList myList = realm.where(MyModel.class).findFirst().getMyList();
How to properly update the UI
The suggestion is using Realm's change listeners. See https://realm.io/docs/java/latest/#notifications
And what is the right way(aka best practice) to use RealmList?
This is a bit confusing, but Realm is introducing RealmCollection into the next major release (v0.89.0). See https://github.com/realm/realm-java/pull/2345.
Note that i cannot hold my information as realmresult directly because im performing some manipulation on the data that i dont want it to be saved.
If the RealmList is in managed mode, the data changes will be saved as well. If you don't want some data to be saved, you could consider to use #Ignore annotation on those fields. See https://realm.io/docs/java/latest/#ignoring-properties
Update on 04072016
RealmList vs. RealmResults:
RealmList is a list of RealmObject saved as a field of a RealmObject. It represents the one-to-many relationship in Realm.
RealmResults is the results of query.
Both of them (if RealmList in managed-mode) will be auto-refreshed when data changes.
You can get a RealmResults from a RealmList by RealmList.where() like:
RealmResults results = myRealmList.where().findAll();
This answer will be a bit out-of-date after Realm v0.89.0 released, because of new RealmCollection.
I'm a beginner in android. I want to perform basic CRUD operations of SQLiteDatabase using AsyncTask class. I have one int and 4 String parameters for table.How do i pass arguments to insert data in table from DataBaseHelper Class to AsyncTask Class.
This tutorial explains the usage of ContentProvider and Loader. Although Content Providers are overkill for small applications, it is the best way to implement a SQLiteDatabase within your application. Basically it allows you to have a app database accessible from every other application you wish and eases the usage of CRUD operations inside any of those.
With it, you don't need any reference to your SQLiteOpenHelper in order to make any operation in your database. Content Providers work by calling getContentResolver().<insert/delete/update>() directly in your Activity, keeping your code clean. Also, every operation you do using this API is sent to the background thread, leaving you no work at all besides configuring it for the first time.
A class that extends ContentProviderwill have 4 methods: insert(), delete(), update() and query(). These same methods must receive an URI that points to the table you will be using in that operation. Cool, huh? 4 methods for every operation in any table. You could also use a Constants class to map your URIs and boom: you got state of the art code.
Is it possible to use ContentProvider for retrieving(query) data from web server?
Some data that are used in App are stored locally and some others stored in web server,I want to encapsulate retrieving data and also storing data by ContentProvider.
Obviously retrieving local data is simple and may be done by ContentProvider.query() method.My problem is in about use that method to query from web.Clearly I can start AsyncTask to fetch data from web,but result returned from query method,before terminating doInBackground() of AsyncTask and downloaded data never used.
So how can I return downloaded data to query method?
Is it possible to use ContentProvider for retrieving(query) data from
web server?
No.
So how can I return downloaded data to query method?
you can not remove the delay of downloading obviously but you can use for example loader and after your data is ready(downloaded) insert it to the database and call
getContentResolver().notifyChange(your uri, null);
or you can use other method like LocalBroadcastManager or EventBus for sending messages to your object to query the ContentProvider again.
I think you can just move AsyncTask from content provider to main app and catch the result, like
new AsyncTask<String, Integer, Cursor>(){
#Override
protected Cursor doInBackground(String... params) {
return getApplicationContext().getContentResolver().query(...);
}
}.execute("");
P.S.
Also I've found interesting words in Google docs :
methods query(), insert(), delete(), update(), and getType()—are called from a pool of threads in the content provider's process, not the UI thread for the process.
But when I've tried to call network operation inside the query method (without AsyncTask) it simply throw NetworkOperationInMainThread exception.
I'm trying to implement the second REST client model presented by Virgil Dobjanschi on this video:
http://developer.android.com/videos/index.html#v=xHXn3Kg2IQE
This is the high level diagram for the model I'm talking about:
I implemented everything as suggested, but I have a complex SQLite database model with lots of tables and I need to use transactions to update my local data with brand new data retrieved from server (step 7 in the picture).
Are there any suggestions you could make to help me out implement a transactional ContentProvider for this case?
Some of you may suggest me to use raw SQLite instead, but this way I won't take the advantages of ContentObservers, managedQueries and database accesses synchronization provided by the ContentProvider.
Any help would be appreciated.
Since you don't have access to the the Level 11 API, you could do this instead. Lets say you want to do this transaction stuff in your update method:
final Cursor update(Uri uri, ContentValues values, String where, String[] selectionArgs)
{
if(uri == uri1){
//do stuff you normally do
}
//other uri stuff
...
else if(uri == special_uri){
//do your transaction stuff here
}
}
In this case, special_uri is a uri you use to indicate that you're going to need to do your special transaction stuff. In other words, we're using the URI here to indicate that a transaction must be done.
You can implement custom function in your ContentProvider that execute your necessary transactions. Then you can call those funcitons using the call() function in your Processor.
Is correct to use ContentProvider with dao Pattern. ? or it will bring any performance issue ?
I will try to explain. I've a contentProvider. an activity, a dao and a bean ..
this is the code :
class Bean(){
String name;
}
class Dao{
Activity activity;
public Dao(Activity activity){
this.activity = activity;
public List<Bean> getAllBean() {
Cursor c = activity.managedQuery(Bean.CONTENT_URI, PROJECTION,
null, null, Bean.DEFAULT_SORT_ORDER);
return BeanMapper.GetAllFromCursor(c);
}
}
}
Class Activity{
.....
onCreate(....){
Dao dao = new Dao(this);
List<Bean> aList = dao.getAllBean();
}
....}
what do you think ?
regards
DAO is designed to provide an abstract interface to a database. ContentProvider already does this.
Yes, you can make a second abstraction layer to provide a DAO API, but... You're programming on a mobile device. Using the ContentProvider API directly is going to be more efficient. There are many examples of this. For example, look at how closely Cursors and ListViews are coupled -- Look at the CursorAdapter classes and you'll see how it's designed to directly map from a database cursor to a list on the screen. Look at ContentObserver, and see how that's designed to push-notify a cursor to update to match a changed database, and in turn, update a single list element in a ListView to reflect that database as it changes in realtime...
You're going to spend immense effort reinventing the wheel trying to get all that existing code to carry through a DAO model. I don't know your application, but I'm not sure I see the advantage you gain from it.