Android Volley - orientation changes
Asked Answered
N

4

17

How can we deal with orientation changes, Activities/Fragments stoping / resuming using Volley ?

I know that for GET requests, the response will be cached and the second time we attempt to make that request, we will get a cached response.(IF the server sends the proper HTTP headers)

But what about POST? Suppose I make a POST requests (i.e. register, which I want to happen only once), my app goes to background, request is finished while app is still in background, and then I go back to the app. How do I get the Response for that Request, or how do I re-connect to it, if it still pending?

AFAIK there is pretty much no support for this in Volley. Am I right? Is there an easy way to solve the above mentioned scenario, using Volley?

Nevernever answered 20/6, 2013 at 16:26 Comment(2)
"How do I get the Response for that Request, or how do I re-connect to it, if it still pending?" -- just because your app is no longer in the foreground does not prevent threads from running. What makes you think that the Request was not already delivered to you? Use a retained fragment for asynchronous operations, so that way regardless of orientation changes, your asynchronous operations have a stable base to communicate to.Jacks
for some reason I had the impression that Volley won't deliver responses if we go to background (like Robospice), but you are right. We have to call requestQueue.cancel(...) to stop the delivery. I'm still thinking of a nice simple way of dealing with re-delivering responses properly during stop/resume.Nevernever
R
8

Volley doesn't provide a mechanism for this out of the box, but you can look into Square's Otto library for Android, it is made to handle situations like yours elegantly.

Implement the Listener for the Volley request so that it posts a successful response onto the Bus, wrapped in an event object like "RegisterEventSuccess" (you define this yourself). Let your Activities or Fragments subscribe to this event type with Otto's @Subscribe mechanism. If - for example - one Activity launches the Volley request and dies because of a screen orientation change, another Activity instance (also registered to the Otto bus) can then receive the event that contains the response of the Volley request.

Hope this was useful.

Referential answered 5/8, 2013 at 11:53 Comment(4)
This solution definitely sounds interesting. Is there a place you have implemented this. Have you encountered any issues?Stalinsk
Not to reopen a dead question but I was looking for some examples of Volley + Otto for request/response management, and this guy put together a pretty clean example of a melding of the two github.com/tslamic/AndroidExamples/tree/master/HttpBinVolleyAerobic
Using this solution, how would you handle the possibility of the network response returning in the moment that the activities are transitioning (between onDestroy of the first activity, and onCreate of the newly oriented one)? Here, neither of the activities will be registered to the bus and awaiting the event. The @Producer methods may address this, but they don't really seem suited to work as a generic network cache and don't really align with the original pattern.Advocation
@kyle-ivey : I have a solution to that in my answer here https://mcmap.net/q/707822/-android-volley-orientation-changes . It is a solution, but probably not the only one. PS: I considered the Producer-method first, but discarded it because it did not fit my pattern.Beore
B
4

I have now attempted to address the concern of @kyle-ivey in that responses arriving in between onPause() and onResume() are discarded. This is a real issue as I have experienced it in a live application.

My approach builds on the event bus pattern implemented in the answer by Thomas Moerman, although I've reimpemented an example application from scratch. It depends on the Otto Event bus Library, Gson and Volley. It is implemented in IntelliJ 13 Ultimate using Maven tom resolve the dependencies.

Solution: I add to the previous answers a class which acts as a HTTP Response Buffer which takes over the responsibility of listening to events while the Activity is transitioning. When done, the activity actively polls for any responses that may have arrived while the activity was disconnected to the event bus. It hooks on/off in the onPause and onResume-events next to the event-bus registering in a fashion like this:

@Override
protected void onPause() {
    super.onPause();
    ServiceLocator.ResponseBuffer.startSaving(); // The buffer takes over
    ServiceLocator.EventBus.unregister(this);    // Unregistering with Otto
}

@Override
protected void onResume() {
    ServiceLocator.EventBus.register(this);         // Re-registering
    ServiceLocator.ResponseBuffer.stopAndProcess(); // Process any responses buffered
}

Here is the implementation of the ResponseBuffer-class.

Caveat 1: If the activity is never resumed, and neither stopAndProcess() nor stopAndPurge() is called in any future activity, the buffer may be a source of memory leak. Be aware of how you use it. A safe pattern would be to have stopAndProcess() in onResume() in all of your activites.

Caveat 2: It is not thread-safe. If there is to come a context switch on the line between where it stars saving and it unregisters the event bus, it may receive the event twice or zero times.

The example includes some test code in the form of UI and support classes, but the main classes you would need if you want to utilize this pattern in a separate projects are the ones in the following packages:

  • nilzor.ottovolley.core
  • nilzor.ottovolley.messages

See the github-repository OttoVolleyDoneRight for a complete example with UI for testing.

Beore answered 15/5, 2014 at 18:44 Comment(0)
R
1

There's a simple solution that solved my problem with downloading data from network using Volley library. If your app uses fragments due to Google's recomendations, than everything you should do to prevent crashing if user rotates the screen while loading data is put setRetainInstance(true); in onCreateView method of your fragment(-s).

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View theView = inflater.inflate(R.layout.fragment_studios, container, false);
    setRetainInstance(true);
    lvStudios = (ListView) theView.findViewById(R.id.lvStudios);
  return theView;
}
Rafi answered 13/9, 2015 at 12:43 Comment(1)
Very old topic, but yet this is the best patternRichart
W
0

Suppose you have login button,On click of Btn your calling server through volley,Suddenly if screen Orientation changes,the volley restart,and app crashes..

so My solution is:on click of Btn first lock screen Orientation,when Volley response comes you Unlock Screen Orientation...

...........here on click---lockDeviceRotation(true) //Lock on Response--lockDeviceRotation(false) //Unlock

public void lockDeviceRotation(boolean value) {
    if (value) {
        int currentOrientation = getResources().getConfiguration().orientation;
        if (currentOrientation == Configuration.ORIENTATION_LANDSCAPE) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
        } else {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
        }
    } else {
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER);
        } else {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
        }
    }
}
Waddle answered 18/9, 2019 at 7:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.