Reputation: 5376
im going to re-ask this question because there is SO much bad information out there its really depressing. the short story is that i dont want anything to change or happen when the device orientation changes. 2 of the most popular "solutuions" given to this problem are:
1.You could lock the activity in one orientation by addingandroid:screenOrientation="portrait" (or "landscape") to in your manifest.
2.You could tell the system that you meant to handle screen changes for yourself by specifying android:configChanges="screenOrientation" in the tag. This way the activity will not be recreated, but will receive a callback instead (which you can ignore as it's not useful for you).
NEITHER of those work. so let me explain my particular problem in more detail...
i am experimenting with a VERY simple app as a learning exercise. i have a text file on a server. the text file has 1 thing in it: a single integer on a single line. this number is the number of image files also stored on this server, and the images are all named 0.jpg, 1.jpg, 2.jpg etc.
ALL of my code is in the onCreate method of my activity (like i said its a simple app).
the app does the following when it runs:
reads the number from the text file. generate a random number from zero to the number in the file. loads a random image into an imageview by using the random number in the URL.
when the screen rotates i do not want all of that to happen again. i simply want NOTHING to happen... except that the screen should obviosuly rotate and the image should scale to fit, which it does. but every time the screen rotates all of that code runs and a new random image is selcted. can someone please give me a simple solution with the working code to fix this? i learn by seeing so if you cant provide a code example it wont help.
thanks in advance.
ps... im not looking for a different way of doing what im doing, thats not the point. im looking to FIX the way im currently doing it.
Upvotes: 8
Views: 17040
Reputation: 8533
Save the image details in your onPause()
or onStop()
and use it in the onCreate(Bundle savedInstanceState)
to restore the image.
More info on the actual process is detailed here http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle as it is different in Honeycomb than previous Android versions.
Upvotes: 0
Reputation: 31
what worked for me is declaring one of the class variables as static. it turns out that static class variables are initialized once when the application is being loaded, but when the application is being reloaded, these won't be initialized again.
these variables could hold a state or an object that you don't want to reinitialize. I can't say that this is not super elegant, but tested and worked for me.
Upvotes: 0
Reputation: 2797
The solution using android:configChanges="orientation"
won't work unless the application has an API level of 12 or lower.
In API level 13 or above, the screen size changes when the orientation changes, so this still causes the activity to be destroyed and started when orientation changes.
Simply add the "screenSize" attribute like I did below:
<activity>
android:name=".YourActivityName"
android:configChanges="orientation|screenSize">
</activity>
Now, when your change orientation (and screen size changes), the activity keeps its state and onConfigurationChanged() is called. This will keep whatever is on the screen (ie: webpage in a Webview) when the orientation chagnes.
Learned this from this site: http://developer.android.com/guide/topics/manifest/activity-element.html
Also, this is apparently a bad practice so read the link below about Handling Runtime Changes:
http://developer.android.com/guide/topics/resources/runtime-changes.html
Upvotes: 11
Reputation: 64690
For example, add to the manifest:
<activity android:name=".Explorer" android:label="@string/app_name"
android:configChanges="orientation" android:launchMode="standard">
</activity>
and then just override the default function:
@Override
public void onConfigurationChanged(Configuration _newConfig){
super.onConfigurationChanged(_newConfig);
int height = getWindowManager().getDefaultDisplay().getHeight();
int width = getWindowManager().getDefaultDisplay().getWidth();
if(width > height){
// layout for landscape
}else{
// layout for portrait
}
}
NOTE: if you override this function YOU must redo the layout yourself. That is the only way to do what you want. Android's approach to fixing your screen size is to blow the entire Activity away and bring it up again with the new dimensions. If you opt to not have it blow the Activity away then YOU have to handle the screen size change. There aren't any other options to that.
EDIT: In this particular app, I have a table that shows up in portrait, and a chart that shows up in landscape. So I do this:
void showDataView()
{
setContentView(mainView);
currentView = mainView;
}
void showGraphView()
{
if(currentView == mainView){
if(graphView == null){
setContentView(R.layout.graphview);
graphView = (GraphView)findViewById(R.id.graphview);
}
setContentView(graphView);
currentView = graphView;
graphView.setDataToPlot(DATA_TO_PLOT);
graphView.clear();
}
}
@Override
public void onConfigurationChanged(Configuration _newConfig){
super.onConfigurationChanged(_newConfig);
int height = getWindowManager().getDefaultDisplay().getHeight();
int width = getWindowManager().getDefaultDisplay().getWidth();
if(width > height){
showGraphView();
}else{
showDataView();
}
if(graphView != null) graphView.setGraphWidth(width);
}
Everytime the orientation changes, I switch the content view from one to the other. In your case you might be able to just invalidate
the current root View and see if it will redraw correctly.
This is why you want the platform to take care of it, so you don't deal with this crap. You'd be better off just using onSaveInstanceState
to preserve the specific data you need and then check in onCreate
for that data and then use it. See http://developer.android.com/reference/android/app/Activity.html#ConfigurationChanges for info about that.
Upvotes: 0
Reputation: 17613
A very similar question is here: Don't reload application when orientation changes
Anyway, first of all you should change the code from onCreate to another method and divide it by "create random number and load image from the net" and "set image to view".
You have a Bitmap on the activity, that you verify if it's null everytime the activity starts.
If it is, do all. If it's not, just set the ImageView or whatever with the Bitmap you have.
To avoid destroying the Bitmap when it rotates use:
Bitmap image = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
image = (Bitmap) getLastNonConfigurationInstance();
if(bitmap == null){
image = downloadImage();
}
setImage(bitmap);
}
@Override
public Object onRetainNonConfigurationInstance() {
return bitmap;
}
This works, i'm 100% sure.
Upvotes: 3