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.
Related
I have my app such that when entered in a certain activity, I show a list of contacts in my phone( similar to Chat app where you see a list of contacts when trying to start a new chat).
So I just wanted to know about the implementation details of these task for best/ efficient work.
Is the contact list is fetched everytime from my device whenever I enter the activity(which is actually redundant, because we maybe doing same work over and over again,
But again we cannot rely on saved data in DB/SharedPref as contacts data is dynamic and bound to change,
so need your expert suggestion how to actually make this work in best possible way(I have already written method to fetch contacts- so whould I fetch the contacts afresh everytime or any other way around is there, what the popular chat apps implemet to show the contacts everytime?
Personally, I would implement the fetching of the contacts on a background thread (using coroutines) that is called periodically (perhaps each time they the activity is created, as you suggested, or maybe once when they open the app).
Because it's on a background thread, it would prevent them using the app (or any dropped frames while the activity is created). They might have thousands of contacts or be using a really slow device.
Presumably, you would want to store some other data associated with each contact: for example, if you opened up a chat with the user, you would want to associate all the messages with the user, so I would use a database such a realm rather than shared preferences.
So the entire process would probably look something like this:
Opening the app triggers a service that fetches all of the user's contacts on a background thread.
Service updates the database, perhaps removing contacts which don't exist and adding the new ones.
If you were handling this in a view model, your fragment or activity could observe the list of contacts and update the UI once it had changed.
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.
I have a use case where I want to download some files from the server and store them locally before starting another activity that is dependent on this file. This kind of design can be found on karaoke kind of applications where clicking on one song would
Load the required files from the server
Once the download is finished, open the required activity.
Let us assume that my app is a karaoke app. My question is how to design this flow. Basically, on clicking on one song, I want to show progress on the screen and when the download is finished, I want to move to the activity. Another requirement is that once I am inside the karaoke activity screen and playing a song, I have an option which leads to loading of another lesson. If a user uses that option, I want to again download the required files. Based on this requirement, should I:
Have the file loading thing as a separate activity?
OR
It can be used as Fragmentinside the activity where I choose a particular song. In this case, once entering the karaoke screen, if I choose an option which leads to downloading some files and reloading of this activity, is this the best design?
I would recommend two different approaches depending on how long you plan on keeping the data that you've downloaded. If it is single use than a bound service would be ideal. However, if you are planning on keeping the downloaded content for more than a single use, I would recommend you use a content provider and possibly a sync adapter(Depending on how frequent/predictable content downloading is). This combo would help guide you into not having to think about the 'design' as much(Since it is pretty standard at this point), plus it would provide a lot of features that you may/may not find useful: you can make your internal data 'public' via the content provider/authority(s), you can make an 'account' on the phone associated with your app so that the user can manage its syncing via the sync manager(actually via widgets/apps using the sync manager, but still), and most importantly a set of clean(ish)/standard means to interact with it/propagate UI, etc.
My simple version would be an Activity that spawns either a async-AIDL service with callback (which is in my opinion the only way to use a bound service) that would allow you to asynchronously design your 'starter' activity, its "currently downloading" spinner (which can get progress updates via the callback if you design it that way). Then once the download is complete then send the results (via a parcel file descriptor in the Intent's bundle) to the new activity that makes use of it.
However, if you are planning on using the data more than once, I'd recommend downloading the content like you did above, but then also store it in a content provider for easy access later. Providers also have a lot of nice associated functionality related to cursor loaders, etc. that will help keep a list of the content currently being stored nice and clean/up-to-date/dynamic/etc. However, this is a lot more work to setup once, then later it would save you time in reduced.
A sync adapter is best when the data to be downloaded is predictable, either based on user's account or temporally (such as someone having an account to download data from (email account, etc.) or when the target is fairly constant, but the data should be updated every hour or so(such as the current weather)). So this will depend a lot on your application's exact specifics.
Here is an assignment for an Android App Development course I wrote that is an even more simplified version of the first option (it has intent service + broadcast receiver for returning download results back to the Activity). Obviously since this is an assignment it has sections cut out to make skeleton code, but the documentation is ABSURDLY detailed and should be fairly easily implemented.
https://gitlab.com/vandy-aad-3/aad-3-assg-2/tree/master
Here is the extension of that assignment for that same course that focuses on implementing a simple content provider's 4 main methods (Create, Read, Update, & Delete). Everything else about the provider is given to you.
https://gitlab.com/vandy-aad-3/aad-3-assg-3/tree/master
Obviously the content being downloaded in both applications is probably not what you intended, but that is a simple swap to replace in what you do want.
Not to shill to hard, but here is the (free) Specialization that this course is a part of: https://www.coursera.org/learn/androidapps
Point one : Don't download video file within the Activity level. You can start a Service to handle it. Once the download function is finished you can start the second Activity. While download function is in progress you can show a ProgressBar
Point Two : Best Design is show a ProgressBar with percentage to user. Or disable the function. After download complete enable or start the second activity.
If I do need it, I'll have to modify about 15 classes (models and model-manager classes), so I really want to know if I need a ContentProvider.
Here's where I am:
Similar to Twitter, I'm getting rows of data from a server, and saving it locally in case the user has no Internet connection. But the ideal way is to always get it from the Server.
I am probably not going to use SimpleCursorAdapter because the rows of data I get from the server includes URLs, which means I have to create a custom adapter to display images.
I need to load data into the ListViews asynchronously because I'm having a ViewPager with 3 Fragments that shows the same data (different filters tho), so, since a ViewPager loads 3 Fragments into memory, it means 3 queries are executing (and that's most likely the cause of non-smooth swiping).
So far, the way I synchronize data between the App and the Server is:
Fragment.onStart() executes an AsyncTask which returns rows of data formatted as JSON data
Said AsycTask.onPostExecute() updates the List<E> and calls Adapter.notifyDataSetChanged()
The issue here is that each time I change tabs, the onStart() is called, ergo the AsyncTask executes causing the UI not being smooth.
Should I change the way I synchronize data with the Server, or should I use ContentProvider?
EDIT: as a head up, the reason I'm asking is that startManagingCursor() method is depracated. It says to use the Loader framework, but it seems it's only available through ContentProvider
You don't need to develop your own provider if you don't intend to
share your data with other applications. However, you do need your own
provider to provide custom search suggestions in your own application.
You also need your own provider if you want to copy and paste complex
data or files from your application to other applications.
from http://developer.android.com/guide/topics/providers/content-providers.html
I wrote a custom CursorLoader based on the SimpleCursorLoader source code that comes within the support library. You can search this site for more information about writing a custom one.
I'm getting hung up on how to handle the data for an app I'm designing. I want to pull a list of items from the net. The data is updated routinely, and I think it would be good to store all the data on the device so the app can load quickly and refresh the data in a background thread rather than have to wait for the network on every start-up.
I think I should make the data available in an XML and have a thread parse and save into a SQLite DB, but I'm not sure if that's the "best practice." Are there other ways that people go about handling this?
The cleanest way (or at least, I think it is the cleanest way) is to implement a custom ContentProvider class that interfaces with your server. You can query the contenprovider and if it doesn't have the data in a local cache (for example a SQLite db as you said) it downloads it from your server and adds it to the local data. Why a content provider? because then you can easily access your data across apps and you have a nice and clean way to get your data when using intents.
Also, I personally prefer not to download data when the app is not running, because it will cost battery life while the user does not actively requests the data.
Sounds reasonable.
If the download of the new data takes more than some seconds, you might want to use a Service. This will allow you to continue the update even when the user has left your app.
Also, think about how you will notify the user that something is going on. Displaying some progress indicator is always a good idea. Otherwise, users might just think the data is not up to date because the app is broken.