I can't find a specific example of this, though it seems like it would be a fairly well-tread path, and one of the primary purposes of a sync adapter. I have implemented most of this but still have some problems to figure out. Here is my basic strategy right now
PerformSync
Figure out the last item stored locally
if there are no local items, pull new items to a certain maximum size
if there are local items, pull new items until reaching local items
delete items over the maximum item size
I have a list adapter with a content observer that should reflect the synced information.
Question:
If all of this is sound, my current dilemma is how an when to delete items from the database. I am assuming I should refrain from any deletions while the content is in use, but in my sync adapter, how do I know if the data is currently being observed? (static map of observers?)
Supplemental:
Beyond that, I would love to have some examples of this in action, so I can anticipate other problems. I know about the google IO talk, it has some great high level philosophy, but specifics would do wonders for many non-guru devs.
I would think this is an extremely valuable function that all Android advocates would want to be done, and done right, as the sync adapter presents one of the most desirable features of Android, and can only help to increase the userbase, helping all of us.
Just a suggestion: maybe sync adapter should only add new items but not delete old ones and deletions should be done by the app.
Note: it seems that in Android Gmail deletions are happening while app is showing emails. Try deleting/archiving message in web-gmail and then menu-Refresh in Android: sync will run in the background and then message will be gone without any notification. So it seems to be acceptable.
Update:
Maybe your sync adapter should check if your activity is active and if not delete old items. How to check if your activity is active: http://www.mannaz.at/codebase/android-activity-foreground-surveillance/
Related
I am working on a social-networking-type app where the user sees a list of "posts" and can interact with them, notably they can "like" them.
The list of posts is in the 10,000s and so we paginate it using Android's paging library (DB + Network), but this is applicable to any situation where there are cached objects that need to be modified.
Loading and paginating the list is working great, very responsive and the built-in animations are nice. The problem is when the user likes a post. In order to like a post, there is a button on the list item. When the user likes (or "unlikes") the post, the button's icon changes and "like count" increments or decrements accordingly and we have to make a call to the appropiate web service. It's all basic social networking stuff and seems pretty simple, but I am struggling with how to update the data correctly and efficiently. So far I've come up with three possibilities but they all suck:
make the request and receive the updated object, then reinsert it into the database. This is easy and ensures that the data is correct but it means that the user has to wait for the request to return before the UI is refreshed, which usually results in the user clicking multiple times on the image (performing multiple requests). So pretty much useless.
modify the UI (the list item view updates it's visual state) but not the backing data, then make the request and insert the result back into the DB. This is a huge PITA as it results in a visual state that is not in sync so if the user scrolls around and comes back before the request completes they will see the original state. I also have to communicate errors back to the view so it can revert its state.
modify the object in memory (change the like count and user-post-like relation), making a copy of the original, reinsert it into the database, make the request, then insert the updated object from the web service or the original object in case of error. This gives instant visual feedback and preserves data integrity but is only mildly less of a PITA.
So for the moment I'm going with 3 because it seems to be the best but I am wondering if there is a better way to handle this? It seems like I'm banging my head on such a basic functionality, surely this problem has been solved a million times before? I am not used to working with caching on CRUD systems (I have implemented basic caching for read-only data) but modifying the cache is turning out to be a bigger obstacle than I expected.
Here's something interesting- How do I display information both from my content provider, and some real-time data from the web (which I don't want to save to my content provider?).
1.CursorLoader and CursorAdapter won't do IMO since I don't want to save the information to my content provider.
2.AsyncTask and updating the view in onPostExecute won't work, since right now I am displaying information from my content provider through cursorAdapter etc. and since the screen itself is an AdapterView subclass, when the loading is finished, the view might belong to some other element (recycled)
3.Service won't do for the same reason as #2 (and besides that, in this case, the background thread is coupled with the UI, so that doesn't seem like a natural solution).
**********Optional specific details starting from here if the picture isn't clear******
Say that I have some app which allows users to follow stocks.
I have a content provider, that at the path content://whatever.my.package.name/follows
has some information about which stock the user is following, whether or not it was sent to my server already (so it does have already some 'real time' data displaying through it), the parameters the user is interested in following, etc.
When displaying this information, I want to include some real time information from the web. I already have the necessary method implemented, but I can't think of a natural solution (see above). In particular, the real time data certainly cannot be saved on the same path (/follows) since this isn't a natural part of what I have in mind when I am thinking about the object "follow",but I do want to present the real time information about the stock, and it does relate to the follow presented on the screen (for example, a follow includes a start price, so we want to present the change from that start price to the real time price of the same stock etc).
I'm can't think of a good design I could use, so help will be appreciated :)
If the only thing that stops you from using the content provider is that you don't want to store the informations in it, then don't store it. Remember that a provider is just some abstraction above some data source. Nobody is going to stop you from using a in memory sqlite database for storing the live data.
Then you have two data sources and can build relations on them for displaying purposes like with sqlites attach_database or in code. Of course the live data is gone as soon as the provider is shut down so you must be able to handle that case.
EDIT
Hmm, ok. So touching the provider is a no go. You said the views are adapter views. How about using Volley or something similar to fetch the data in the adapter itself and cache it there. Whenever a view is requested (i.e in 'onBindView' when using RecyclerView) check the adapter cache for the data. If it does not exist or is outdated start fetching the data. When the request returns notify the adapter that the dataset changed. It then would start requesting views again making the next cache probe a hit. If you are fetching the data for each item in the cursor try to pass the index/position of the item to the request so that you can notify the adapter that a specific item has changed.
I have read a lot of SO answers asking a similar question, but I believe my question is different. I have to load around 70-80K records from the cloud and display it to the user in a ListView. A few things that I want to be done :
I don't want to use a load more Button or load more objects when the user scrolls as I have a index from A-Z so the user could start my application and click on Z and the data should be present/available to him.
I have considered pre fetching the data using a splash screen but I was wondering if there is really any other optimised method to fetch such huge data.
I don't want to hang up the UI thread with the Loading progress bar.
I agree that this may be too much to ask for but I am just trying to see if someone has a very efficient way of doing this. I am open to ideas involving modifications in the backend on web service as well, so if you have an efficient way of achieving this using some modifications on the web service, that is also fine for me.
If it helps, look at your default contacts app, it has all the data ready and available to you when you open it. You can directly use the index to navigate to Z section. Just assume the same with 70k entries in the app.
Thanks in advance!
Here is the best solutions I figured out with the help of Tamal Mukherjee and Roman Nurik.
Tamal's solution :
Just load 5-10 rows/letter. Add a 'more' button or handle scroll event and load dynamically. Use SQLite to store data. Use background threads to fill up the db.
Roman Nurik's soltuion :
With 80k rows, that's well over 1000 items per letter in the alphabet. Seems like you'll need a lot more than letter indexing to make this UI usable. Why not offer filter-as-you-type? That'll result in more HTTP requests but might result in a better UX.
So i guess my implementation will be a combination of the both.
Please follow this step:-
1- Call API on splashscreen using IntentService.
2- Use static broadCasting and save API response into sqlitedb using ORMLite in onRecieve() method of BroadCastReciever.
3- Make sure there should be separate class for receiver.
4- Use Loader Manager for updating ListView.
We have a certain type of app that is connected with server through Socket. Server usualy sends some orders (Adding orders, Updating them, and Deleting). Server sends more the 20 requests per second. And depending on those requests to Android client we have to change ListView Adapter. We are doing that, but nevertheless we have a huge load of CPU.
What do you think can be the root of this problem?
ListView implemented with ViewHolder. We do not know where to measure time and how we can define the bottleneck of this particular app.We were trying to measure parcing of request - it is ok. Also we measure view notification. It seems that it is also not to slow. View then trigered through View.post(). Maybe that MessageQueue to View is too long?
Edit: CPU load is huge even if we are not currently in the ListView (We are not seeing it)
you could refer to this amazing blog post made by Romain Guy (one of the main Android Framework engineers) that shows how to use several optimisation tools. Most of the tools showed are already included in the SDK and measure pretty precisely stuff with times in milliseconds, etc.
Very useful reading for any android developer
edit:
just a wild guess here, considering your description, maybe the CPU load comes from the mobile have to process all the information, even if the information is not relevant to it (you said that depending on the request, you change the adapter) why not make the server check this data and only send to the device what will actually be used?
Well, 20 requests per second is heavy task for mobile device itself (not just ListView).
ListView reloads all contents everytime you add something, so if you adding new items at the bottom of list, then it's better to load new items only when user reaches last item of list.
If you are adding new items at the top of list, then ListView is not really suitable for your purposes. Consider creating your own view instead and providing different implementation for onLayout method.
EDIT
Also, consider using some kind of buffer, which will hold accumulate information and then flush it to UI thread (instead of posting every request to UI thread).
My application allows users to chat with friends (like skype or whatsapp), so I have an Activity for displaying a "conversation" (a list).
The user can change from one conversation to another.
So, the problem is changing from one list to another, or "updating" the whole list of messages.
What is the best way to do that? (performance and memory)
- Remove all elements from the list and add the new messages?
- Use multiple ListViews and Adapters?
...
Thanks!
I'd say it all depends on how you're storing the messages, and a lot of other parameters revolving around that.
However, I would probably cache the messages locally so that when the user selects a new conversation, they first get the to see the old messages while loading the new ones. One ListView, one ListAdapter of some sort and a List that I clear out when switching between conversations.
That might not be the most optimal approach, but that's how I'd do it in the given scenario.