I would like to have all my Activities (7 to 10 different screens) submit data to a "controller" (sorry if I'm miss using the term).
Inside said controller data would either be uploaded or saved to data for uploading when no internet.
The controller would do checks and processing such as:
Checking for valid session.
Attach other needed credentials before
upload etc.
Session/User data would be stored in a Shared Preferences file the controller has reference to.
My goal is to have Activities do nothing more than collect the data and call the appropriate method (with a data object) asynchronously. The controller would know how to process the data for uploading or saving in the database.
Would placing these methods in an extension of Application be a bad idea?
It was mentioned that depending on application size this is feasable, but there could be better solutions.
Depending on the size of your project, that would be a suitable idea. However, there are some other ways you should know before choosing the method you're actually implementing:
Using a ContentProvider for your data, an AccountAuthenticator and then sync to the server using an SyncAdapter. Advantages are a good abstraction, independence from activities and many built-in features (for example: Android executes your code without a big battery life impact). However, implementing all the stuff is quite much work at first. If you don't want to use the ContentProvider, the same technique works with a stub implementation as well, the same goes for the AccountAuthenticator.
Using a Service, probably IntentService, for your uploading needs. Advantage is that the Service has an independent lifecicle and thus is not directly related to your Activity; a Service can get restarted if it has been killed by the system. Still more work than just using some static methods.
Using a static method as you're proposing it (in your case, the Application object; not completely static, but compareable). Quite easy to implement, probably the best way if there are similar tasks in multiple activities; your AsyncTasks can send their result directly to the activitiy that started it. However not suitable for long-running tasks.
Implementing within the Activity; If code is only used once; listed for completeness only, not for your case. Basically the same as using a static method.
These are the ones that popped into my mind, there might be some others, too. Feel free to add/suggest additonal ones.
Related
Just wondering what is a better practice to pass information between activites, adding it to a bundle or using a singleton class to store and access this data. I have used both in the past for various android side projects, but I am now working on an android project that is of much larger scale, so would prefer to do things right towards the beginning.
My application authenticates users and then will have to do various queries based on it's id. To minimize coupling between activities, I would think just adding the id to the bundle, and then letting each activity query for the information that it needs, would be the best bet; however to increase responsiveness, I was leaning towards using a singleton class to store persistent information, preventing more queries than need be.
Personally, I would create an extension of Application to store the state of your app and share data between the different activities. The Application acts as the context for your whole app and Android guarantees there will always only be one instance across your app. Hence it works similar to defining your own Singleton, but using Application will allow Android to take control of the life cycle of your shared data and basically do the memory management for you.
Here are some more details. If you go down this path, you can simply add any getter/setter (or other) method to your application extension to store/retrieve data and do operations on it. Especially the latter can become quite a pain to manage (and keep consistent) when using Bundles passed back and forth between activities. If would only use a Bundle if the data is needed in just one or two places that are neighbours in the activity flow and does not need any (complex) operations to be run on it.
The better way to go for you is to use SharedPreferences to keep userId you need to keep and reuse. Of course you can use singleton approach or even Application class, but the data will be lost after application is killed.
The only time I pass data between Activities via bunlde is if it's something that I won't need to access for a while(i.e the the resID of a resource I want to use only once in the calling activity, etc). I would also think the difference in responsiveness would be very minimal, so that shouldn't be of concern. I suggest the singleton approach
Passing bundles is a tedious job. You'll have to pass a bundle for every change in activity to make sure that the value is not lost, even if you're not using the value in the called activity.
Singleton pattern have some bad results. For example:From Main activity you call secondary activity. Phone call interrupted your work.After ending phone call Android is trying to bring secondary activity to screen. Here is my nightmare - many users complaint about exceptions - Google reported to me NULL pointers in my singleton. So you have to provide not only singleton, but all data inside singleton have to be as singleton too. This maked come very complicated :(
I am new to Android. I’m attempting to write an application which will display multiple pieces of information about open stores. I get that information using a RESTfull API which passes JSON data.
Here is my question: What is the best service/threading implementation choice?
Here are my product requirements:
• I want to encapsulate all the API and JSON into a class that one or more Android “Activities” can call. I think this might dictate a service but this service will only need to run when my application is running and will not be accessible by other applications. The user will be required to authenticate into the remote system via the RESTfull API.
• It will have to be on a separate thread because of the possibility of the API calls taking too much time. I don’t think it will need to be multi-threaded since I don’t see more than one “Activity” will be interfacing with the service at a time.
• The service should look at caching some of the information it gets back so that when an “Activity” makes a call (“GetStoreList” for instance), it could return a list of stores it already queried earlier. I’m not sure if I should keep this information in memory or try using the SQLite functionality in Android. I could have several hundred stores in the list with ten to twelve other pieces of information associated with each store. Some of this information would be displayed in the “Activity” list view and some won’t. Since I don’t have any experience with SQLite, I’m not sure what the performance cost would be over storing the information in memory.
• There will be about a dozen or so methods that the service will need to encapsulate. For instance: once I get the store list, I may want to call the API again to find out if the store is currently open. Some of the information passed will be custom classes and therefore would require “Parceable” class definitions if I have to use IPC’s as part of my solution (if I understand the Android documentation correctly).
• I would also like to “Lazy-load” the list into my “Activity” so that I don’t have to wait for the full list before updating the user interface.
Possible Solutions (this is all guessing, so please don’t crucify me… that’s why I’m asking the question):
I could use a class extended from “Service.” It would have to handle the threading itself so that long internet calls via the RESTful API wouldn’t hang the system. Alternatively, I could do the thread manipulation first and call the API with the assumption that I can take as much time as I want. I think I would need to implement communication between the “Activities” and the service via IPC’s. This seems a little complicated to me. I’m not sure if I can use the “Messenger” class. It looks easier than the AIDL stuff.
I think I could use an “IntentService”. This would automatically create a separate thread and queue messages/tasks. I think I could communicate with the service (to get the lists of stores for instance) by “Binding” to the service. The problem I see is passing data back and forth and I’m not sure how I would cache the data between calls to the API since the service terminates after making the API call.
Anyway, I’d rather learn from someone who has already done this type of app instead of doing it the wrong way and coding it twice.
Thanks for the help.
AbstractThreadedSyncAdapter was made just for stuff like this. There's a fairly comprehensive (but complex example) here. Also, one of my favorite Google IO videos gives a pretty good overview of how to use it.
Your scenario is almost exactly the same as ours in my previous project. Here's what we came up with (I'm sure it's not original, but is patterned from one of those google io videos too)
A Service handles the request-response of RESTful calls to the server. This is triggered by the activity calling startService(Intent) that includes the parameters in a Bundle included in the intent. The Bundle contains information as to what API will be called, and what parameters are included.
The Service doesn't directly pass the result to the activity - instead it writes the result to an sqlite database. The activity will know that the transaction is finished by observing the db (via ContentObserver). Similarly, the Service can notify the activity once a transaction is completed via broadcast; the activity can catch this by registering a BroadcastReceiver - however the resulting data should still not be directly passed to the activity via Bundle, as there may be cases where the data is too large for the Bundle to contain (there's a limit for the length of a String that can be included in a Bundle) - you still want to put the result in the Provider. The activity should query for the data as soon as the Service notifies the activity that the result is there.
Additionally, you can include a "success" or "fail" flag in the Broadcast that the Service will throw for the Activity, so it will know if it still needs to query for result - this removes an additional overhead for failed transactions.
If you need to ask, No we didn't use AIDL for this architecture (but we did use it on another module that does facebook/ym chat over xmpp).
The "lazy-loading" I think can be asked in a different question, as it is an entirely different process.
I'm currently learning to develop for Android and I'm having a somewhat hard time figuring out when and how to use services. I have already seen the numerous questions asked about very similar things, but I can't quite find the exact answer to my questions.
I have an app which talks to a restful api. I fetch several lists which I would like to cache in memory and only update if the user hits a refresh button, or certain activities are created. If a list is refreshed, sometimes several activities need to be notified, so that they update their content (if they are on screen at the time). I store the data I retrieve in value objects.
On a non-android app I would usually create a sort of dataproxy class in a singleton pattern. I could ask the dataproxy to update its data via http request, and then it would send some kind of system-wide notification as soon as the data is changed, so the interested views can all be updated. I hope this makes sense.
My question is now: How do I do this the android way? Do I bind and unbind to a dataproxy service, which I can actively ask to fetch certain data? Should I do my non-persistent caching in this service or somewhere else? Do I need AIDL, or can I just use normal objects for moving data between a service and an activity? Although I find the android dev guide pretty well written and useful, I haven't found much information on services best practice.
Thank you in advance!
How do I do this the android way?
You assume that there is a single "android way".
Do I bind and unbind to a dataproxy service, which I can actively ask to fetch certain data?
You can either bind, or send commands via startService().
Should I do my non-persistent caching in this service or somewhere else?
If you're sure that you only want it to be in RAM, I'd lean towards static data members. Make the service be the "do-er", not the store.
That being said, I'd treat this more as a synchronization pattern, with the real store being a database or directory, with a cache in RAM. Users will find this less frustrating -- under your current plan, if they are in your app, then take a phone call for a while, they'll have to have you download all the data again.
Do I need AIDL, or can I just use normal objects for moving data between a service and an activity?
If they are all in the same process, normal objects is fine via binding, or use Intent extras for the command pattern.
Now, back to:
How do I do this the android way?
Option #1: Wrap your store in a ContentProvider and use ContentObserver for changes.
Option #2: Have your service send a broadcast to your package when the data changes, so the foreground activity can find out about the change via a BroadcastReceiver registered via registerReceiver(). Other activities simply grab a fresh look at the data in onResume() -- the only one that immediately needs to know of the data change is the one the user is interacting with, if any.
Option #3: Use the binding pattern with the service, and have the foreground activity register a listener with the service. The service calls the listener when data is updated. Once again, ather activities simply grab a fresh look at the data in onResume()
Option #4: Cook up your own listener system as part of your static data members, being very very careful to avoid memory leaks (e.g., static reference to an activity or service that is destroyed, preventing its garbage collection).
There are probably other options, but this should get you started.
The Google IO session mentioned by Andrew Halloran:
http://www.google.com/events/io/2010/sessions/developing-RESTful-android-apps.html
Check out the Google I/O session videos. I implemented REST api calls the easy BUT wrong way. It wasn't until watching this Google I/O video that I understood where I went wrong. It's not as simple as putting together an AsyncTask with a HttpUrlConnection get/put call.
Im wondering what is the point of using a android service to do background work when you need to do a lot of things just to access any public methods or get a large chunk of data from a service such as a larger List object.
why not just use a simple POJO that does stuff in the background for you in a seperate thread if you like and gain access to its public methods without creating interfaces using AIDL, binding to a service etc etc?
seems soo much work needs to be done to access a method from a service class or is that really not the point of a service class in android?
i have developed a android service class that gets 100's of items in a xml structure from a web service who i then parse it into a POJO that is then stored in a List but i am having difficulty finding a way to send this List back to the activity that called this service.
i've read about using parcebales objects but that along with all the intent.putExtra have a size limitations so i may run into problems in the future.
i am thinking of ditching Android services and i have quickly found out why i dont like using them in the first place :(
a simple SomeBackgroundPojo backroundTask = new SomeBackgroundPojo(); backgroundTask.getData();
Seems soooo much easier than dealing with parcelables, serealizable objects, AIDL, binding etcc etc all just to achieve the two lines of code i just typed above :(
Nitpick: an object running a threaded background task ain't precisely what's usually meant by a plain old Java object.
If you don't care what happens to the work being done if its requesting Activity or Application is shut down, then by all means avoid services. One of the main points of Services is that they can stay alive when the user navigates away from an Activity: if you're only doing work to fill a UI ListView, by all means use e.g. an AsyncTask, as is discussed in this earlier question.
This is a question I've now had for a few different apps I've built, and I have yet to be satisified with any of the solutions I've come up with. I thought I'd put it out there to the community to see other solutions there might be.
Let's say you have an Activity that downloads a complex tree of data (in this case via json, but it could be anything), unmarshalls that data to a set of java objects (in this case using gson, but again, could be whatever), then spawns additional activities to view different parts of that data. There might be one activity to view Trips in your response, and another to view Flights in those trips, and maybe another to view Passengers of those flights.
My initial implementation of this app was to unmarshall all the Trips in the first activity, then pass them by value (as an extra in the intent) to the TripActivity. The TripActivity then passes individual flights to the FlightActivity, and so on.
The problem with this is that there's a noticeable pause between activities while the app serializes and deserializes the data. We're talking several seconds. The pause is quite noticeable when my tree uses Serialization or Parcelable to pass data around. Initial performance testing with using google's Parcelable instead show a roughly 30% speedup over serialization, but Parcelable is difficult to work with and doesn't seem to handle circular object references well like Serialization does, and besides it still pauses for almost as many seconds, so I've put that experiment on the backburner while I try other things.
So then I tried moving the tree of objects directly into the Application class. Each activity just gets the tree directly from the app whenever it needs it. This makes performance quite snappy, but handling corner cases like unexpected activity start/stops (either due to activity crashes or because the activity has been closed temporarily to make more memory available, or whatever other cause) seems tricky. Perhaps it's no more than implementing onSaveInstanceState(), I'm not sure, but the solution seems a bit hacky so I haven't investigated further yet.
So in search of a less cobbled-together solution, I tried creating a custom ContentProvider to store and retrieve my objects. Since ContentProviders can be configured to run in-process using multiprocess=true, I thought that would be an excellent way to avoid serialization costs while doing something more "standard" than storing data in the Application object. However, ContentProviders were clearly not intended to return arbitrary object types -- they only support types such as numbers, strings, booleans, etc. It appears I can finagle one to store arbitrary objects by using ContentResolver.getContentProviderClient().getLocalContentProvider() and accessing my custom class directly, but I'm not sure that's less hacky than storing data in the Application object.
Surely someone must have a good solution to this problem. What am I doing wrong?
In addition to fiXedd's solution, another one is to use a local service. Have the service "own" the objects, with activities calling service APIs to get whatever it needs. The service can also be responsible for fetching and parsing the data, encapsulating that bit of logic.
The Application object is the "red-headed step-child" of Android components. Members of the core Android team have come out against the practice of creating custom Application subclasses, though it is certainly supported by the API. Having engineered one ADC2 200 application that leveraged a custom Application subclass, I can say that I should have gone with a service in my case as well. Live and learn...
By using the local binding pattern, your service will automatically be created and destroyed as needed, so you don't have to worry about that. And, by definition, a local service runs in the same process/VM as your activities, so you don't have to worry about marshaling overhead like you would in the ContentProvider scenario.
The way I'm handling this in one of my apps is downloading the data then shoving it into a database. This way I don't have to carry all those objects around (which, IIRC, eat about 1kb each just for the object instantiation) and I can easily pull just the data that I need. I don't know if this will work for you, but it worked for my use-case.
Another approach would be to save the data objects to a shared preferences file. That's how we implemented one of our apps, but I didn't like that approach because it seems too slow.
It's bad coding practice, but the fastest way may be to just use a service to parse the data and save the data to a static class that you can use for the rest of the app's life.