database operation in android loader - android

I'm using a LoaderManager, the onCreateLoader method creates a new CursorLoader.
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle data) {
return new CursorLoader(context, CONTENT_URI, PROJECTION,
null, null, null);
}
Only after loading is finished in onLoadFinished() the UI is updated.
Every time I load the cusor I also need to do some database manipulation like building up a new sort index. This cannot be done asynchronously because the UI depends on this.
Is there a way to do such db operation within the loader? Or what is the best design for this problem?

As per your question you are loading your data in from database using loader and content provider
also you are working on sorting type of thing which can change the order of item in database...
So, the best way I suggest as per my experience in this type of application of do this of index sorting operation in UI only util user leave the screen...
So, In you activity of fragment override onStop method and update data indexes in database based on sorting priorities or numbers...
and after updating data to content provider just notify URI for change..
hope my point is clear to you..

Loaders were designed specifically with optimizing database access in mind. This operation does not care about updating the UI and hence has no interest in providing progress information. While it is possible (and I use this loosely), to update the UI from a loader, you should avoid this as the Loader is a wrong tool for this job. Forcing a Loader to provide progress information would break the paradigm. The Loader is expected to return only after the etire operation is complete. Instead, if you want to update the UI while doing the querying, then you should use an AsyncTask.
If you HAVE to use a Loader, then you can find a workaround here at Update progressbar from AsyncTaskLoader?. But again, since from your question, it looks like you are open to alternatives, use the AsyncTask if you need updates or you can stick to Java threads.

Related

CRUD using LoaderManager and CursorAdapter

I have a MyListFragment implementation which uses MyCursorAdapter. As the names suggest, they both extend the respective Android classes.
I read through this Loader/LoaderManager tutorial. So, now my query happens in
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(blah1, blah2, blah3, blah4, blah5, blah6);
}
and the LoaderManager along with the Loader takes care of when to re-query and update, runs separate threads for queries, synchronize without having me to worry about it. So far so good.
I have 2 questions:
1) I have implemented a MyContentProvider. Where does this come into picture?
-> It seems that the above new CursorLoader(......) makes the query through the MyContentProvider since it uses the URI as the first argument.
2) I also need to delete / update / insert items in the list. Should I just call my the respective methods from MyContentProvider inside MyListFragment at the desired places? If yes, then can I also load the items manually, without having the loader handle it? If not, then what is the right way to do it? I did not find any information online. Any pointers appreciated.
Yes, thats correct it will call the query method in MyContentProvider with the arguments used in the CursorLoader constructor.
If I understood that correctly the answer is yes you can just call the MyContentProvider methods as long as they are calling ContentResolver.notifyChange() as it will cause the CursorLoader to get a new cursor (this is the whole point of using CursorLoader). When using CursorLoader you should avoid manually changing the data at all if you can so as to allow what is shown to always reflect the current set of data coming from MyContentProvider.

Android: Using a Loader to make http request, update SQLite database & populate GridView fragment

In my Android app, I am making a http request, getting some data, putting it in my local sqlite database & then populating a gridview using that data. I have the code working for an activity but I need to use fragment now to get this done as there are many similar pages to be shown. I read that using Loader is the best way to deal with data in a fragment.
I am not sure about:
Whether to use CursorLoader, Async taskLoader or SQLiteLoader(developed by commons guy).
In which of the loader functions (onCreateLoader(), onLoadFinished() etc.) do I put my code for making http request, populating the local database & getting the data displayed in a gridview in my fragment
I am also using a lazyload list to show images. How will that fit into the entire thing if I use loader
Can anybody help me with this one? Tried searching for good examples or tutorials but I haven't really found something that's really useful. So, please suggest any if you can. Thanks
Whether to use CursorLoader, Async taskLoader or
SQLiteLoader(developed by commons guy).
CursorLoader is for ContentProviders(which is not your case) and AsyncTaskLoader is the way to go. I haven't use the classes from Commonsware but if they allow overriding of some of their methods then I guess you can use it.
In which of the loader functions (onCreateLoader(), onLoadFinished()
etc.) do I put my code for making http request, populating the local
database & getting the data displayed in a gridview in my fragment
In none of those callbacks because they run(most likely) on the main UI and you must not do network operations in there. The Loader subclasses have the loadInBackground method which runs on a background thread. On this method the Loader queries for data and in which you could place your networks requests and database updating. But you would need to be very careful to not insert duplicate data in the database.
I am also using a lazyload list to show images. How will that fit into
the entire thing if I use loader
As I haven't seen your code, I don't think this two parts are connected. I'm guessing that you use the lazy image loading code directly in the GridView's adapter.
My advice is to not use Loaders for loading and inserting data because their purpose is to only load data on a background thread(having taking care of configuration changes). For your particular situation I would make my own AsyncTaskLoader(or use Commonsware's library) which queries the database for new data. I would then start a new AsyncTask to do the http request and to insert data in the database and then I would trigger a Loader restart in the onPostExecute method of the AsyncTask(with getLoaderManager().restartLoader...). Have a look at this similar question for some problems related to what you're trying to do.

Inserting records via Loaders in android

This question would be a follow up from the one asked Content Resolver vs Cursor Loader
Where the answer clearly states how to insert records into a sqlite Db using a Content Resolver . My question is the following :
Can i use a loader(Normal Loader) to implement this functionality ?
eg :
public Loader<Cursor> onCreateLoader(int id, Bundle bundle) {
switch (id) {
case AppConstants.LOADER_ADD_FAV_PHONE_NUM:
ContentValues values = new ContentValues();
values.put(DBHelper.TM_DB_COLUMN_PHONE_NUMBER,
directionOrder);
values.put(TransitMeDBHelper.TM_DB_COLUMN_NAME_ID, selectionArgs[0]);
Uri insertFavStop =getContentResolver().insert(TransitMeContentProvider.CONTENT_URI_INSERT_FAV_PHONE,
values);
break;
}
return null;
}
Would this run the functionality in the Main UI thread or a worker Thread . I understand that i would not receive callbacks for this as the content resolver will return a URI instead of the cursor containing data .
I tried running this code but it behaves kind of wierd .. Duplicate inserts are recorded and its not consistient , Could someone show me to some right resource which uses a Loader to do Insert operations ( I have seen many examples with query examples and it works like a charm :) )
Thank you for your time .
Can i use a loader(Normal Loader) to implement this functionality ?
You can't use a default CursorLoader to insert data. If you implement your own Loader you could probably use the loadInBackground method to do the insert but that will make your code awkward at best(and I don't know if it will actually work).
Would this run the functionality in the Main UI thread or a worker
Thread . I understand that i would not receive callbacks for this as
the content resolver will return a URI instead of the cursor
containing data .
The loader callbacks will run on the thread where they are implemented(the UI main thread most likely) so you're doing the getContentResolver().insert() on the main UI thread with the possibility of blocking the main UI thread.
I tried running this code but it behaves kind of wierd .. Duplicate
inserts are recorded and its not consistient ,
Have you tested how many times is the onCreateLoader method called?
Could someone show me to some right resource which uses a Loader to do
Insert operations ( I have seen many examples with query examples and
it works like a charm :) )
Don't use/try to use a Loader to insert data in the ContentProvider/Database. It works like a charm for queries because the loaders were designed to load data from a data source(not insert data), that is their purpose. If you want to insert data use an AsyncTask(also have a look at AsyncQueryhandler), a regular thread.

android - CursorLoader & SQLite without Content Provider

I know this has been discussed yet I wanted to ask about the current state of the matter. Do i have to create a ContentProvider to use CursorLoader in connection with a sqlite database?
I found
CursorLoader usage without ContentProvider
Looks exactly what I was hoping for yet as Emmby commented
Users should be aware of one limitation, which is that it has no mechanism to refresh on data changes (as Loaders are supposed to do)
So another solution is mentioned
https://github.com/commonsguy/cwac-loaderex
yet again some drawback is pointed out
However, to make use of the automatic re-querying, you need to use the same loader for the UI as well as for the updates, limiting its usability for background services.
Of course when using LoaderManager we want to get all the benefits for which it was introduced. So my question is if there is a way to use LoaderManager in connection with a sqlite database without having to implement a content provider yet have all the benefits of it.
Thanks
The two implementations you mention in your post both offer all of the benefits of the CursorLoader except the ability to receive notifications when the underlying content changes.
I've been looking into this a lot recently and I can confidently tell you that the Android API currently does not provide a means of doing this with only a raw SQLiteDatabase (it only provides the ContentResolver#notifyChange() and Cursor#setNotificationUri() methods, which are used to notify all Cursors registered under a certain notification Uri).
That said, your options right now are to:
Implement an observer yourself that is capable of receiving notifications from the SQLiteDatabase when the content changes, and is somehow able to relay these notifications to all existing Loaders in your application. I wrote a pretty extensive blog post on how to implement Loaders that might come in handy if you wish to take on this challenge. Or...
Use Mark Murphy's LoaderEx library and only make database modifications using the AsyncTask operations his library provides. Note that the reason why his tasks refresh the Loader is because they call onContentChanged on the Loader immediately after the insertion/update/delete is performed, effectively telling the Loader that the content has changed and that it should refresh its data.
Just use a ContentProvider with a CursorLoader and you can use the ContentResolver#notifyChange() method to notify the CursorLoader that a content change has occurred.
I'm trying to figure out a better solution, and I'll report back in the future if I ever find/implement one, but for now these will have to do.
Here is my solution, in my onCreateLoader
{
Uri u = Uri.parse("content://what_string_you_want");
return new CursorLoader(this, yourURI, projection, null, null, null) {
private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver();
#Override
public Cursor loadInBackground() {
Cursor c = YOUR_DATABASE.doYourQuery(...);
if (c != null) {
// Ensure the cursor window is filled
c.getCount();
c.registerContentObserver(mObserver);
}
c.setNotificationUri(getContext().getContentResolver(), getUri());
return c;
}
};
}
After the code that will change DB, add
getContentResolver().notifyChange(
Uri.parse("content://same_with_first_string"), null);
how about having a boolean in shared preferences as false .. updating the content when that boolean is true....
and when any of the operations which changes the underlying database .. that boolean will be set to true and as shared preferences you a changelistener you can recieve changes live directly after the relevant methods are called

how to write a asynchronous content provider in android

i'm writing a content provider that provides search results for other applications.The content provider sends requests to server and parse response.now it can work successfully without asynchronous calls.but if i want a asynchronous content provider,that is,creating a thread in the query() function.and then comes the problem,how can i know when the thread is finished and has got the results.because now i just new a Thread,and start it,however,the cursor could not get results.anybody can help me?Thank you!
My application has this same problem. Depending on your situation, you may be able to return an empty cursor from your query call, and then have your views update when the cursor's data is updated. If it makes sense with your data source, you can subclass MatrixCursor (or another cursor) and make sure to call onChange when the cursor's data is updated after the asynchronous request completes - this should notify that cursor's observers of the new data, and then they can show it.

Categories

Resources