android screen orientation conflict - android

I have a method in my main class, that fetches some data from the internet. The thing is that after everything is done, if I change the screen orientation by moving the device, everything starts allover again(fetching data while displaying a loading screen). Is there somewhere I could put my method so that if my device's screen orientation changes, it won't erase everything that has been done until that moment? Thanks.

What is happening to you is that every time you rotate your activity is recreated, as per android good practices you should handle your activity being recreated because android may destroy your activity at any point if resources go low on the device. Take a look at saving the state of your activity and how to restore it and the link.
Example using onSaveInstanceState()

You can use a singleton class to store your data.
If you prefer a simpler way you can also put your data as static, so the orientation change will not throw them away.

I think that your Activity is getting recreated again. In that case,it will load again.
1). You can handle orientation change by overriding
public void onConfigurationChanged(Configuration newConfig)
and in your activity declaration in manifest file add the following line
android:configChanges="orientation|screenSize|keyboardHidden"
2). As Aerilys said in the above answer, you can use singleton class to store data. Before displaying your loading screen check if you single ton object has data or not. If yes then skip displaying your loading screen

Related

Locking Android orientation based on preference

No, not a regurgitation of the old question, please, bear with me. I don't want to avoid activity recreation in general (no android:configChanges in manifest), I don't want to fix my orientation permanently (no android:screenOrientation in manifest) just because I'm lazy to implement instance saving.
I have an app with three possible settings the user can make: 1. automatically changing layout on orientation, as per normal, 2. fixed portrait, 3. fixed landscape. It makes sense in my case because the portrait and landscape displays show different functionality and the user might want to restrict to just one. Doesn't have to but has the possibility.
The app works just fine. I read the preference setting in onCreate and call setRequestedOrientation if I'm in one of the fixed modes. I let the system handle the orientation changes, I don't ask for handling the changes myself.
The only performance problem is that when, for instance, the app is started in the device's portrait position but fixed to landscape, onCreate will be called twice, once for the original startup, once for setRequestedOrientation. It works flawlessly, I handle it perfectly but there is a performance penalty, the activity appears with an obvious delay. (With screenOrientation fixed in the manifest, only for the purpose of testing, the startup looks much better, with only a single call to onCreate).
So, what I'm looking for is a kind of code equivalent of the manifest screenOrientation setting. I can't and don't want to specify it in the manifest but calling it from onCreate is already a bit late for performance.
Try to read users preference in Application Class, and in the onCreate setContentView on the basis of that value.
public class MyApp extends Application{
public void onCreate(){
// get user preference here in a global variable
}
}
Set this as application class in Manifest.
Then in your activities onCreate, use this value to determine layout before setContentView().
did you try this?
<activity
android:name=".YourActivity"
android:configChanges="orientation|keyboard|keyboardHidden|screenSize|screenLayout|uiMode" />
This configChanges line on the manifest file should avoid the re-calling to the onCreate method :)

Storing complex computed data between orientation change

In the onCreate() of my MainActivity, my app does an intensive operation to generate some data set (runs in a separate thread, but takes some 2 - 3 seconds to complete normally). Now my problem is that, when orientation changes, the app again does this complex computation again.
Since I haven't done anything like this before, I was wondering if there is a way around this. My first thought was to store the computed data in a static variable, so that the data is persisted between different instances of MainActivity. I am guessing this is not the best approach.
My data set consists of a Map and an ArrayList and not a simple data type, if it helps.
I have looked at the onSaveInstanceState(), but it only provides to store values like int, String, etc.
In addition to what #Raghunandan suggested you can read the official docs on Recreating an Activity .
It says:
Your activity will be destroyed and recreated each time the user rotates the screen. When the screen changes orientation, the system destroys and recreates the foreground activity because the screen configuration has changed and your activity might need to load alternative resources (such as the layout.
It also introduces the concept of
onSaveInstanceState()(To save additional data about the activity state, you must override this method) and
onRestoreInstanceState() method (The default implementation of this method performs a restore of any view state that had previously been frozen by onSaveInstanceState(Bundle)).
You can also see the sample implementation of these methods here Saving Android Activity state using Save Instance State thread, which will help you to save and restore the state.
Update
You may also try using:
<activity name= ".YourActivity" android:configChanges="orientation|screenSize"/>
The docs for android:configChanges say;
It lists configuration changes that the activity will handle itself. When a configuration change occurs at runtime, the activity is shut down and restarted by default, but declaring a configuration with this attribute will prevent the activity from being restarted. Source: How to save state during orientation change in Android if the state is made of my classes?
Hope this helps.

Forcing Android to not redraw activity on orientation change

I have been going gaga to figure this out.
Although I have read a lot that on Orientation Change, Android kills an activity and starts it as a fresh one, and the only way to handle this is to save all the stuff inside onSaveInstanceState() and try to restore it inside onCreate().
But my activity does a lot and different kind of network activities at different times and if the orientation is changed when the network activity is being performed, I'll have to handle a lot of different and complex scenarios.
Is there any simple way to just point Android that this activity doesn't need to be redrawn at all when the orientation is changed so that it automatically saves all the data and re-uses it?
I wonder if there's any thing like that.
Yes, you can add attribute android:configChanges="orientation" to the activity declaration in the AndroidManifest.xml file.
EDIT:
The purpose of the android:configChanges attribute is to prevent an activity from being recreated when it's really necessary. For example the Camera application uses this attribute because it the camera preview screen mustn't be recreated when an orientation change happens. Users expect the camera preview to work without any delays when they rotate their devices and camera initialization is not a very fast process. So it's kind of a native behavior for the Camera application to handle orientation changes manually.
For most applications it doesn't really matter if an activity is recreated or not during orientation changes. But sometimes it's more convenient to persist an activity during this process because of slow activity creation, asynchronous tasks performed by an activity or some other reasons. In this case it's possible to tweak an application a little and to use the android:configChanges="orientation" attribute. But what is really important to understand when you use this tweak is that you MUST implement methods for saving and restoring a state properly!
So to sum up this answer, the android:configChanges can allow you to improve the performance of an application or to make it behave "natively" in some rare cases but it doesn't reduce the amount of code you have to write.
But my activity does a lot and different kind of network activities at different times and if the orientation is changed when the network activity is being performed, I'll have to handle a lot of different and complex scenarios.
Then move that logic out of the activity and into a service.
Yes, you can add attribute
android:configChanges="orientation" to
the activity declaration in the
AndroidManifest.xml file.
IMHO, it's better to declare
android:configChanges="orientation|keyboard|keyboardHidden"
About the blog post you gave the link in another answers. I guess here is the answer:
If your application doesn't need to
update resources during a specific
configuration change and you have a
performance limitation that requires
you to avoid the Activity restart,
then you can declare that your
Activity handles the configuration
change itself, which prevents the
system from restarting your Activity.
I spoke as well with an android developer about this problem. And he meant following. If you don't have different layouts for landscape and portrait orientation, you can easy use configChanges.
I solved my problem by adding this to my activity in my manifest file
android:configChanges="keyboardHidden|orientation|screenSize"
Just answered this question earlier: Android - screen orientation reloads activity
In your case you want to completely prevent Android from killing your Activity. You'll need to update your manifest to catch the orientation change, then implement the orientation change callback to actually do whatever you need to do (which may be nothing) when an orientation change occurs.
if you are doing a lot of networking inside Asynchronous task maybe you should use onRetainNonConfigurationInstance()
ans then get the data back in your onCreate() method like this tutorial or this
add android:configChanges="orientation" to your activity in manifest and add this code in your activity class and check..i hope it will help for you.
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
setContentView(R.layout.main);
}
this method will be called when orientation is changed nothing else if u don't want to change anything let it be blank
android:screenOrientation="portrait" in the activity tag in the manifest will lock your orientation.
Check this link for more inforation.

Android web app gets restart

I am facing problem in building android webview . The problem is that when the app is running and phone change direction , i mean from horizontal to vertical or vice versa the app get restarted. Thanks
The default behavior is to restart the activity when the screen orientation changes. You can write custom code to handle orientation change events yourself though:
Add android:configChanges="orientation" to your AndroidManifest.xml
Override onConfigurationChanged from your activity
The default android behaviour is to destroy and recreate the activity on orientation change. You can either override onSaveInstanceState() to save your application data before destroy, or you can call onRetainNonConfigurationInstance() to keep hold of a stateful object. See the android docs.
Umar,
You will want to add the android:configChanges="orientation" parameter to your Activity in your AndroidManifest.xml to prevent your activity from restarting on orientation change.
See: http://developer.android.com/guide/topics/manifest/activity-element.html#config
Another possibility (usually a decent fit for lighter Activities that don't have state outside a WebView, for instance) is to absorb the rotation event and let the view redraw itself. See http://www.androidguys.com/2008/11/11/rotational-forces-part-three/ - the idea is:
Put an android:configChanges entry in
your file, listing the configuration
changes you want to handle yourself
versus allowing Android to handle for
you.
Implement onConfigurationChanged()
in your Activity, which will be called
when one of the configuration changes
you listed in android:configChanges
occurs
See also: Activity restart on rotation Android
umar... Saving instance state is quite different on the Android. On a soft kill (phone rotation) you may save your non view state in onSaveInstanceState using bundles. On a hard kill (back button while activity has focus) you may elect to save your non view and view state in onStop perhaps using preferences. You can restore your state in onCreate.
You can leverage the fact that IF onSaveInstanceState is called it will be called BEFORE onStop. So this lets you set a flag isSavedInstanceState to true in onSaveInstanceState to avoid saving prefs in onStop except on a hard kill. The trick is to reset the flag isSavedInstanceState to false in onResume NOT in onCreate.
JAL
I have sample code here.

Gracefully handling screen orientation change during activity start

I'm trying to find a way to properly handle setting up an activity where its orientation is determined from data in the intent that launched it. This is for a game where the user can choose levels, some of which are int portrait orientation and some are landscape orientation. The problem I'm facing is that setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) doesn't take effect until the activity is fully loaded. This is a problem for me because I do some loading and image processing during startup, which I'd like to only have to do once.
Currently, if the user chose a landscape level:
the activity starts onCreate(), defaulting to portrait
discovers from analysing its launching Intent that it should be in landscape orientation
continues regardless all the way to onResume(), loading information and performing other setup tasks
at this point setRequestedOrientation kicks in so the application runs through onPause() to onDestroy()
it then again starts up from onCreate() and runs to onResume() repeating the setup from earlier
Is there a way to avoid that and have it not perform the loading twice? For example, ideally, the activity would know before even onCreate was called whether it should be landscape or portrait depending on some property of the launching intent, but unless I've missed something that isn't possible. I've managed to hack together a way to avoid repeating the loading by checking a boolean before the time-consuming loading steps, but that doesn't seem like the right way of doing it. I imagine I could override onSaveInstanceState, but that would require a lot of additional coding. Is there a simple way to do this?
Thanks!
Solution:
As per Daniel's answer, this was actually quite easy to fix. I just needed to make a few small changes. In my 'menu' Activity, where the player would choose which level to play, I just had to add an if/else check to choose which class would be started by my Intent. This was done with a simple int representing portrait or landscape, determined when the player selected a level. I then created a second class extending my 'GameLogic' class; this is the class which contained most of the code for the game itself, rather than the menus, instructions, etc.
public class GameLandscape extends GameLogic{
}
Literally that simple and completely empty. That way it inherited all the code from my previous activity where I had already coded it to handle things differently depending on the orientation. Lastly I just had to add a line to the manifest stating that GameLandscape would always run in landscape, and GameLogic would always run in portrait.
So a simple problem indeed.
You could make two Activities - one for portrait levels, the other for landscape levels - and then set the Activity's orientation in AndroidManifest.xml, using the android:screenOrientation attribute. You won't even have to duplicate code if you use inheritance; use your current Activity as the base activity, and just create the landscape/portrait Activities as subclasses of that Activity.
I think a better solution would be for the Intent to open the correct Activity of these two, though if you must have everything be routed via Intent extra analysis, you could forward all levels to a third Activity that does nothing more than analyse the Intent and then forward it to the proper Activity.
You could also override onRetainNonConfigurationInstance(). This lets you temporarily store one item that you can retrieve by calling getLastNonConfigurationInstance(). That way you can load all of the stuff that you need and in your onRetainNonConfigurationInstance() method you can save it all into a data structure and return it. The in your onCreate() you can call getLastNonConfigurationInstance() and if that returns null load, load all of your stuff, if it return something, then you have it all loaded. Here's a quick example:
public class MyActivity extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
DataStructure myData = (DataStructure)getLastNonConfigurationInstance();
if(myData == null)
{
// Load everything in
}
else
{
// Unpack myData
}
}
#Override
public Object onRetainNonConfigurationInstance()
{
DataStructure myData = new DataStructure();
// Put everything in to myData
return myData;
}
}

Categories

Resources