Fragments, setRetainInstance(true), and threaded libraries - android

Here, Dianne says that the old methods of retaining objects via onRetainNonConfigurationInstance() are now made obsolete by the fact that you can retain Fragment instances over configuration changes.
And here, in the API Demos for fragments, it shows how to use this method for maintaining threads after a configuration change.
I see that during a configuration change, when the Fragment might not be attached to any activity and the thread is done doing it's work, it's able to call wait() so that it doesn't try to deliver results while an Activity isn't attached. I find this very useful, and a great way to mitigate one of the more pain-in-the-butt problems with Android orientation changes.
However, if you're using a threaded library (an API library that uses a thread executor, for example), where you don't have access to wait() on said threads, how could we use this new feature to our advantage?
How can we ensure that messages won't be delivered while an activity is not attached?
I've been thinking of a way to maybe queue up messages and delivery them when a new Activity is attached, but I wanted to hit up you guys and see if you've already come up with some solutions.
Also, note, I've looked into the LoaderManager API, and it seems like it would be good for data that needs to be loaded when an Activity is shown, but not for something event based, like logging in via a button, etc.

You could get around this issue using a higher level concurrency utility such as a Latch, which you could have all of your threads wait on until the new Activity is attached (just before they try to access the message queue to deliver their result).
Once the Activity is attached, you can release the Latch, allowing all the threads to deliver their results.

Related

Starting singleTask activity every few seconds gives ANR in Android

In the app I have an activity which has launch mode as singleTask. There are number of use cases which pass through this activity and hence it's called number of times. On stress testing the app by running monkeyrunner script and calling this activity every few seconds causes ANR's.
I guess, the way it's designed where most of the use cases pass through this activity is not correct but I am not in a position to change this design.
Is there anyway ANR's can be suppressed? I mean, adding UI operations to event queue so that it doesn't block main UI thread and doesn't give ANR.
It is unclear from the question what your activity is (or should be) doing. Probably you need a service instead.
It is common to perform time-consuming operations in background threads and deliver the results to the UI thread.
You may use the classes Handler/Looper (it it easir to send Runnables rather than messages), or use an AsyncTask. The AsyncTask is nevertheless tricky, this is discussed here: Is AsyncTask really conceptually flawed or am I just missing something? . AFAIK Google tried to fix the typical bugs and made the new behavior incompatible with the old one (namely, I have seen some misbehavior on the newer Androids that may be explained by the assumption that since some version threads doing asynctask jobs get killed after the activity that started them goes out of the screen).
I can guess that singleTask is your way to fight the fact that an activity dies when the screen turns, and a new one comes. I suggest you use singletons (they survive screen rotation but do not survive a process restart, one more thing that sometimes happens in Android). (The user switches to an app like Camera, takes a big photo, returns back -- and the activity is restarted because Camera needed memory. Have seen this in practice, but that time I did not try to find out if the whole process was restarted.)
Anyway, please add logging telling you when your activity in entered and left, including onNewIntent() and other lifecycle functions (to be on the safe side, I recommend to print the thread names as well). Then you will probably see what is going on.

Robospice request never ends if app goes in background and then comes to Foreground?

I am developing an app using RoboSpice library for calling REST API's. Everything works fine with the library except one thing. I don't use caching available in RoboSpice and so all the requests are made without cache. Now, when any request is going on and the user presses the home button then onStop() is called where shouldStop() of spice manager is called which unregisters all the request listeners for notification. When, the app again comes to foreground then UI update doesn't occur as the listeners have not been notified.
I don't want to use Cache that Robospice offers. Is there any other way that one can get UI update notifications without using Cache??
It's clearly not possible with RoboSpice, and indeed, there is a good reason : it would be a very bad idea.
When your activity dies (onStop), Android wants to garbage collect its instance. And to do it, it should not be referenced by anything. That's why RS imposes that all listeners are removed. Typically listeners hold a reference to the activity (as inner classes) and the finest achievement of RS is to let the activity die properly and get garbage collected.
So, doing what you want would clearly lead to a memory leak, and moreover would lead to crashes most of the time: when an activity is not displayed anymore, you would like to update its UI ? Looks a bit ackward, doesn't it ?
Maybe the simplest would be to use a very limited cache, or just execute all your requests every time your activities enter in onStart.

Best practice to handle orientation change: Android

I was going through various practices to handle orientation change with threads and AsyncTask. I came across following solutions:
Attach-detach model : Attaching and detaching activity to threads and AsyncTask while preserving their instance. (Source: 1, 2)
Headless fragment way : Using a non-UI/headless fragment to do all the thread related operations and retaining its instance on configuration change. (Source: 1, 2)
Are there any other approaches to handle this scenario? What is the recommended practice? I'm asking this because I couldn't find a generic solution anywhere in the Android docs.
Some summaries
There are several methods mentioned above that are good practices but I thought I might sum them up with short explanations. Below are some of the most popular libraries being used currently for http networking, asynchronous work / threading, and caching.
My current project (just preferences)
I personally am currently using Otto, Loaders, Volley, Ormlite, and a network stack based on Apache and Services. I do hope to replace, the network stack at some point with either Volley, Retrofit, and maybe eventually Robospice.
I personally very much like Otto and Volley
RoboSpice (Modular)
https://github.com/octo-online/robospice
http://www.youtube.com/watch?v=ONaD1mB8r-A
a plugin / modular approach to long-running tasks
this is like the "swiss-army-knife" of libraries, but you need to know what each tool does.
Handles REST calls
persists data through orientation and other changes
can handle disk and memory caching )
works with various HTTP libraries and persistence libraries (Gson, Jackson, Spring, OkHttp, and many of the below libraries)
beta for Ormlite support, I think
Retrofit (REST)
https://github.com/square/retrofit
Annotation library to make REST very easy. Works with Robospice.
Volley (Networking data & Images)
https://android.googlesource.com/platform/frameworks/volley
https://developers.google.com/events/io/sessions/325304728
This is the networking code that runs the Google Play Store
Fast, reliable
Handles most caching for you with some sensible defaults
very easy to use
built specifically for very fast image, json, etc loading
Handles all threading for you.
Picasso (images)
https://github.com/square/picasso
Http library for loading images
fast
very easy to use
Loaders (Android)
well supported
persist through orientation change and save/load of fragment state
can be difficult to get right
no caching
AsyncTask (Android)
simple way for background work from the UI thread
must be canceled and be careful about tasks that return after an activity or fragment is torn down.
Otto (event bus)
https://github.com/square/otto
Event bus that makes a-sync work between components and fragments easy
Very powerful #Produce ability retains the last event and can produce it on demand for any new interested subscribers to the bus
Headless Fragments (?)
I personally have never seen this used other than Vogella's tutorials, so I'm not sure on this one.
Service (Android)
The old school way
ultimate control, you must do everything yourself
usually used with Appache or HURL client and
pass Parcels around via Intents
Why don't you try Loaders, in particular AsyncTaskLoader? They are available for pre-Honeycomb through Support Library and perfectly match Activity/Fragment lifecycle. Here is the official summary:
They are available to every Activity and Fragment.
They provide asynchronous loading of data.
They monitor the source of their data and deliver new results when the content changes.
They automatically reconnect to the last loader's cursor when being recreated after a configuration change. Thus, they don't need to re-query their data.
We are actually using RoboSpice library. It runs on a Service with only providing RequestListeners objects.
The problem with your first approach (Keeping references between the AsyncTask) is that you can probably generate memory leaks because when your AsyncTasks holds your Activities references, they will be not garbage collected. Keep an eye on this just profiling your application checking Heap Size rotating the same Activity over and over again. Your heap should grow in the normal parameters (There is a moment when your objects that must be garbage collected lives at the same time with new objects) but when GC runs your RAM allocation should fall to the same size that you've allocated at the beginning.
So if I have to recommend something will be the next thing:
Activity managing API Calls and Flows (With RoboSpice, letting de UI rotate)
Simple screens inside Fragments using retainInstance in true. This let to you pass your DTOs directly to your fragments, and you have to only manage the state at the top level Activity.
If handling asyncTask is your main concern i.e not willing to download data each time orientation is changed then you may try like this --
(1) Initialize any value before on create like this ..
Boolean android_hacker = false;
(2) Now when you are done with downloading data on AsyncTask class then set that value to true
android_hacker = true;
Here maintain all data utilizing model and Array adapter class
(3) Now each time orientation is changed then check like this
if( android_hacker = true ){
// Use your saved instance ..
}else{
// Download data as it is yet not downloaded ..
}
Hope it helps ..
There are many ways you can try beside the AsyncTask. And if you try to find a best practice, AsyncTask isn't a good option. This answer explains why you should not use AsyncTask. And they recommend you using a better way which can deal with long running task, RoboSpice. I have already used this library and I think it is worthy to try: respect activities lifecycles (orientation change), no memory leaks, supports multi-threading, caches results... It can plug and unplug long request task by using cache (but it can't work well for a non-cache request).
But I recommend a good way comes from Google: IntentService and BroadcastReceiver. You will registered and unregistered broadcast during orientation change to receive the data result. All background task will work in IntentService and notify whatever you want to activity by BroadcastReceiver. There are a lots of example that you can try. Something like this: http://mobile.tutsplus.com/tutorials/android/android-fundamentals-intentservice-basics/
Update:
Hi R4j, the point is my application is quiet complex. And I've to make
number of parallel network calls. Your approach with IntentService is
good but isn't suitable for complex scenarios
I don't think this is a problem. You can do anything with the IntentService, even the complicated tasks. If you want parallel tasks, you may consider a Service with multithreading in it and communicate with activity by Intent. Sending intent between Service and activity is safe and flexible, that is Android way.
And if you want to cache (by file download, stream, by database..) RoboSpice is a best choice for you
You can try with the following approaches:
1) If your application does not explicitly require any orientation changes, just disable orientation changes at the beginning of app execution, thereby you would be avoiding any crashes or related problems with respect to orientation changes.
This you can do using the following line in the outermost layout of your layout xml file:
android:orientation="vertical"
(for setting vertical orientation)
2) You can set or preserve previous orientation values at the beginning of your thread execution using Asynctask, as follows (syntax example only):
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
and
getResources().getConfiguration().orientation

Is System.exit(0) really that dangerous?

An application background service updates sqlite database. Therefore my activities are becoming outdated. Activity intents also contain outdated params so onCreate, onResume will crash the application. An easiest solution is to restart whole application. I don't want to add IFs to all onCreate, onResume methods in all activities to handle one special case.
I noticed that ACRA has following code executed after an exception has been handled.
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(10);
However many people discourage use of System.exit(0). Is System.exit(0) really that dangerous for an Android application data integrity? Of course my code will close the database before existing.
Update:
I known how to use finish(), content providers, send broadcasts, read many answers here on SO, etc. However each of these approaches requires additional thousands lines of code. I implemented solution with System.exit(0) in ten minutes. The restart is so fast that it is indistinguishable from ordinary startActivity action. The db update/restart is done after longer user inactivity so the app is already suspended by the system. My app doesn't require real time syncing. During tests the application behaves correctly. This is quick and dirty solution.
Therefore I asked the question about possible side effects of System.exit(0). Not how I can do the design differently. I know that current design is not perfect.
System.exit(0) is an artifact from Java runtime, it isn't meant for Android. So in any cases using it would be worst solution.
Why don't you use Activity.finish() gracefully?
If you terminate the process you are living in, you'll loose most of the caching and restart time (~resume in the eyes of the user) for it next time will be higher.
Read more in Activity Lifecycle documentation on Android Developers.
Killing the process will not clean up any registered resources from outside the process. BroadcastReceivers, for example. This is a leak and the device will tell you as much.
You really shouldn't be updating the database schema from a background service. Do it when your activities resume.
If you are just updating your data, resuming an activity should validate the data specified by the Intent and tell the user if, for example, Item X is no longer there.
No tool is that dangerous if used carefully and for a specific, well thought off purpose.
However, In your case I do not believe System.exit() is the right way to go. If your application depends on data from a database, create a background service (or a few, depending on what you need) that will inform your application of changes and update the data. It is, in my opinion the right way to handle changes.
As for scenarios when you want to use System.exit() I personally sometimes use it when I can't recover from a critical error and no graceful degradation is possible. In those cases it is better to force all resources associated with your application to cease rather than just leave loose ends tangling around. To clarify, you should always use error handling before doing anything radical. Proper error handling is often the way to go.
But this is a very delicate topic and you are likely to receive quite a few diverging answers.
Therefore my activities are becoming outdated.
Use a ContentProvider and ContentObserver (or the Loader framework), or use a message bus (LocalBroadcastManager, Otto, etc.) to update the activities in situ.
Activity intents also contain outdated params so onCreate, onResume will crash the application
Copy the relevant "params" to data members of the activities. Update those data members as needed (e.g., from the handlers from the message bus-raised events). Hold onto that data as part of your instance state for configuration change (e.g., onSaveInstanceState()). Use this data from onCreate(), onResume(), etc.
An easiest solution is to restart whole application
It is not easiest, if you value your users, as your users will not appreciate your app spontaneously evaporating while they are using it. Do you think that Gmail crashes their own app every time an email comes in?
Next, you will propose writing a Web app that uses some exploit to crash the browser, because you cannot figure out how to update a Web page.
I noticed that ACRA has following code executed after an exception has been handled.
A top-level exception handler is about the only sensible place to have this sort of code, and even there, the objective is for this code to never run (i.e., do not have an unhandled exception).
There's an existing answer HERE that might give you some help as to why people say it's bad to use System.Exit().

Android - Efficient way to pass event notifications to activity that may not be active?

I have a complex app that has background threads (that could be in a service) which, when they receive data from the internet, need to notify my main display activity (to update on of several status indicators). All run in the same process (I see no reason to do otherwise).
However, in some circumstances, these events are frequent - 5 per second. Also, the events may occur when the activity is not-visible or even destroyed. I think the only thing novel about this question is the issue of efficiency. I still target the G1, for example.
There are a number of methods mentioned in this thread, but I don't know which of these are efficient enough, and will work if the activity is destroyed. Those methods are the "Android way" which I would prefer to follow.
I have three ugly anti-Android ways that work, but they also have drawbacks:
Have a thread in the activity that is waits on a semaphore, and when released, does the update. Disadvantages: extra thread, how to handle several event types
Like #1, but use a concurrent blocking queue object. Disadvantages: extra thread, same type of event may end up in the queue multiple times (not good)
Keep a static reference to a handler on the activity, and use that to run an updater. Disadvantages: (a) may leak a reference to the activity? (b) what happens when the activity changes state? (c) multiple runnables could end up there when only one is needed.
Also, the events may occur when the activity is not-visible or even destroyed.
If your activity is destroyed, there is nothing to update. If and when the user elects to re-visit that activity, the activity can get the current information in onResume() for display.
If your activity is in the background, there is nothing that needs to be updated, either. Again, if and when the user elects to re-visit that activity, the activity can get the current information in onResume() for display.
The ONLY time you need an activity to be notified of events in real time is if that activity is in the foreground. In that case, any of the solutions I outlined in the answer you linked to could work. The binding option or Messenger are probably the lightest-weight solutions.
I have a complex app that has background threads (that could be in a service)
Not "could be" -- "must be", if they are to live beyond the scope of any given activity instance.
I have three ugly anti-Android ways that work
None of those work without potential memory leaks.

Categories

Resources