Avoid restarting http request on orientation change

by patbenatar » Sat, 17 Apr 2010 12:57:37 GMT

Sponsored Links
 Hey all-

I've run into an interesting little issue.. My loader Activity fetches
data from a web API, starting an http request and waiting for the
result.. Now what if the user flips their phone mid-http request? The
Activity is destroyed and restarted, thus the http request restarts as
well. The fact that my Activity is being destroyed on orientation
change is all good by me, I understand the way Android works, I'm just
looking for a solution to avoid restarting the http request on every
orientation change..

I'm thinking the solution would be Services... I could run a Service
in the background to do the http request and when it finishes, call
back to my Activity and let it handle the data and finish up. The one
thing I'm a bit weirded out about is what if the user closes my app
before the Service's http request finishes? What will it do with the
data if the Activity that needs it is no longer running?

Thoughts, feedback, ideas, etc would be great!



Avoid restarting http request on orientation change

by Bob Kerns » Sat, 17 Apr 2010 14:47:30 GMT

 You are 100% on the right track; this calls for a service.

As for what happens when your activity is no longer running -- well,
let's consider that.

First, if your activity is simply no longer the current activity --
the user may have pressed Home, for example -- he may switch back to
it. You'd like to have actually made some progress in the meantime --
especially if he left because he was tired of waiting for the
transfer. You probably want to let the transfer continue until
onDestroy() is called on your Activity, at which point you can stop
the service.

If your activity is truly gone -- well, would that information be
useful if he started up your program again later? If so, you might
want to consider allowing the transfer to finish, and caching the
result. In this model, the activity's onDestroy() method leaves the
service alone, and the service calls stopSelf() when it's done. Next
time it's started for this purpose, it can check for the cached data
and immediately supply that.

If caching is inappropriate, and you want it to only run when the
Activity is still alive, then use bindServce() instead of
startService(), and  unbind the service in the Activity's onDestroy().
The Service can track how many bindings are active, and exit early out
of its loop reading the data. You couldn't do any better than this at
stopping the activity even if you were doing it in the Activity


Sponsored Links

Avoid restarting http request on orientation change

by patbenatar » Sat, 17 Apr 2010 18:46:12 GMT

 Awesome. Thanks Bob! This has been very informative. I will pursue
this route :)

> >

Avoid restarting http request on orientation change

by Dimitris » Sun, 18 Apr 2010 02:02:41 GMT

  would take into consideration that onDestroy() might not get called
always. Usually onPause() is the best place to store/cache data before
you are done because it is guaranteed to get called. Keep in mind not
to do "expensive" or time consuming operations onPause() because the
other activity that is trying to show won't show until your onPause()
is done.

I recommend reading the Android activity life cycle docs on the
android dev docs.

Enjoy :)

On Apr 17, 3:45am, patbenatar <patbena...@gmail.com> wrote:
> > >

Avoid restarting http request on orientation change

by Bob Kerns » Sun, 18 Apr 2010 05:54:00 GMT

 f this were a matter of saving the data, then onPause() is indeed the
place to do the work. However, it's not appropriate here.

This is not something you want to pause. You increase the chances of
connection failure, and you consume resources on the server. Don't do

You also don't want to stop it there, and restart it on resume. That
just causes extra work, and minimizes your chance of success.

onDestroy() is the right place to actually destroy the background
activity here, if you want it to continue while the activity continues
to be "active". Yes, in some circumstances onDestroy() won't be
called, and the process will just be deleted. That will also nuke the
service, though, so that doesn't present a problem.

On Apr 17, 11:02am, Dimitris <dnkou...@gmail.com> wrote:
> > > >

Avoid restarting http request on orientation change

by patbenatar » Sun, 18 Apr 2010 10:00:05 GMT

 greed, Bob. I will pursue your above route :)

Dimitris- Thanks for the input. I have read the Activity lifecycle
docs and believe I have a pretty solid understanding of the Activity
lifecycle, this issue is however more related to the Service

On Apr 17, 2:53pm, Bob Kerns <r...@acm.org> wrote:
> > > > >

Avoid restarting http request on orientation change

by Michael Elsd枚rfer » Sun, 18 Apr 2010 14:25:27 GMT

 Depending on your specific needs, a service might make sense, but for
simple cases, it's not strictly necessary. You can instead use
Activity.onRetainNonConfigurationInstance(), which allows you to pass
live Java objects to the new Activity instance - i.e., for example an
AsyncTask object. Just make sure you don't create leaks by keeping
references to old instances of your Activity around.

I've been using a custom ASyncTask child class for a while that allows
me to "connect" to the task from a new activity instance, and have the
proper callbacks be executed even if the tasked finished in-between
activities being available:


Note that while the docs say that onRetainNonConfigurationInstance is
only for "optimization", it's not quite clear what that the official
contract is. Yes, it's possible that your activity needs to restore
itself without onRetainNonConfigurationInstance(). For example, if the
user leaves your application via HOME and then goes into the Settings
and changes the device language, your activity will be stopped and
restarted, presumably without onRetainNonConfigurationInstance() being

However, it might be ok if in those cases your api request will indeed
need start again fresh, depending on it's duration, and maybe whether
it changes state on the server. But for your run of the mill
orientation change, onRetainNonConfigurationInstance() is apparently
being reliable called, and it has been suggested on this list a number
of times that it is intended to be used for objects that can't be
stored in a bundle, like for example sockets.



Avoid restarting http request on orientation change

by patbenatar » Mon, 19 Apr 2010 16:22:19 GMT


An interesting approach indeed. Sounds a little hacky, though...
Especially if the docs vaguely advise against it as you mention. A
clever hack, though :)



Other Threads

1. findViewById returns null MapView when following maps tutorial

I'm following this tutorial here:

and am on point 11

Here's the res/layout/main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/
  android:layout_height="fill_parent" >




Here's the code:

package com.example.hellomapview;

import android.app.Activity;
import android.os.Bundle;
import com.google.android.maps.*;
import android.widget.LinearLayout;
import android.widget.ZoomControls;

public class HelloMapView extends MapActivity
        LinearLayout linearLayout;
        MapView mapView;
        ZoomControls mZoom;
        /** Called when the activity is first created. */
        public void onCreate(Bundle savedInstanceState)
                linearLayout = (LinearLayout) findViewById
                mapView = (MapView) findViewById(R.id.mapview);
                mZoom = (ZoomControls) mapView.getZoomControls();

        protected boolean isRouteDisplayed() {
                return false;

Here's the manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    <uses-permission android:name="android.permission.INTERNET" />
    <application android:label="@string/app_name">
        <uses-library android:name="com.google.android.maps" />
        <activity android:name=".HelloMapView"
                <action android:name="android.intent.action.MAIN" />
android:name="android.intent.category.LAUNCHER" />

I've built both this project and the avd I'm loading it to as target
3's, meaning they should have maps capability, and have acquired a
proper Maps apiKey (which I've hidden in this post)

If I back up to step 6 in the tutorial, everything works, which means
the map loads and I can pan around, but when I try to reference the
MapView in the xml with this line:
                mapView = (MapView) findViewById(R.id.mapview);

the view returned is null.

Here's the ant debug output:

$ ant debug
Buildfile: build.xml
    [setup] Project Target: Google APIs
    [setup] Vendor: Google Inc.
    [setup] Platform Version: 1.5
    [setup] API level: 3

     [echo] Creating output directories if needed...

     [echo] Generating R.java / Manifest.java from the resources...

     [echo] Compiling aidl files into Java classes...

    [javac] Compiling 2 source files to /home/doubleagent/Programming/
    [javac] Note: /home/doubleagent/Programming/ANDROID/HelloMapView/
src/com/example/hellomapview/HelloMapView.java uses or overrides a
deprecated API.
    [javac] Note: Recompile with -Xlint:deprecation for details.

     [echo] Converting compiled files and external libraries into bin/

     [echo] Packaging resources
 [aaptexec] Creating full resource package...

[apkbuilder] Creating HelloMapView-debug.apk and signing it with a
debug key...
[apkbuilder] Using keystore: /home/doubleagent/.android/debug.keystore

Total time: 2 seconds

Any idea what I could be doing wrong?


2. Null reference for ImageView

I have the following xml layout:


       <ImageView android:id="@+id/pacAnim"


PacManMainView extends SurfaceView. I can draw to this, it works OK.
However, when I attempt to get a reference to the ImageView from
PacManMainView like this:

public void surfaceCreated(SurfaceHolder holder) {
   /* test reference to imageview
   ImageView pacImageV = (ImageView) findViewById(R.id.pacAnim);

I get a null each time. Is there something real simple Im missing?



3. accelerometer

4. click animation

5. how can i pass object in intent?

6. weird drawing on bitmap to canvas

7. How To Keep ListView Header From Scrolling With ListView Content