1

I am making a demo app to illustrate how I handle screen orientation. It is a simple counter app that increments the count when the user presses the increment button and viceversa. Here is my code, I included android:configChanges="keyboardHidden|orientation" in manifest file and also overrode onConfigurationChanged method. But unfortunately, I am unable to preserve the value of the count and when I switch emulator to landscape orientation the count is reset to 0, how do I go about this problem?

public class Counter_demoActivity extends Activity {

int count=0;
TextView tv;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    //UIActivity();
    Button add1=(Button)findViewById(R.id.btn1);
    Button sub1=(Button)findViewById(R.id.btn2);
    tv=(TextView)findViewById(R.id.tv1);
    add1.setOnClickListener(new View.OnClickListener() {
    public void onClick(View v) {
        count++;
        tv.setText("Your Count is " + count);
    }
});
   sub1.setOnClickListener(new View.OnClickListener() {

    public void onClick(View v) {
        count--;
        tv.setText("Your Count is " +count);
    }
});
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
    // TODO Auto-generated method stub
    super.onConfigurationChanged(newConfig);
    setContentView(R.layout.main);
    //UIActivity();
}
/*public void UIActivity(){
    this.tv=(TextView)this.findViewById(R.id.tv1);
    this.count=getChangingConfigurations();
}*/

}

My manifest file:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.arif.counter_demo"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="14" />
<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" 
    >
    <activity
        android:label="@string/app_name"
        android:name=".Counter_demoActivity"
        android:configChanges="keyboardHidden|orientation|keyboard" >
        <intent-filter >
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

</manifest>
Arif Nadeem
  • 8,524
  • 7
  • 47
  • 78

6 Answers6

3

Why you are Overriding onConfigurationChanged while you don't have need to do this...in your case.don't remove android:configChanges="keyboardHidden|orientation" in manifest file just remove the code

@Override
public void onConfigurationChanged(Configuration newConfig) {
    // TODO Auto-generated method stub
    super.onConfigurationChanged(newConfig);
setContentView(R.layout.main);
//UIActivity();
}

from your project.Clean it and rebuild ...

Last Warrior
  • 1,307
  • 1
  • 11
  • 20
1

Remove this method

@Override
public void onConfigurationChanged(Configuration newConfig) {
      ....
}

and Make sure in manifest you are adding

android:configChanges="keyboardHidden|orientation"

With Counter_demoActivity or some where else?

Just Use below line and check if your activity is recreating or not? Log a line in your activity on create method and then change orientation. Is line appear in logcat or not?

android:configChanges="orientation|keyboard|keyboardHidden"

Arslan Anwar
  • 18,746
  • 19
  • 76
  • 105
1

You don't say what didn't work, but I'll venture a guess. You're getting a null pointer exception somewhere. One problem with your code is that you'll need to repeat most of the logic that you have in onCreate() when you execute onConfigurationChanged. You have an entirely new set of views in the activity. Otherwise, the member field tv will be null and there won't be listeners attached to your buttons.

EDIT From your comment that count isn't being preserved, I believe that there's something wrong with your manifest and the system is destroying and re-creating your activity on orientation changes. To preserve count across such changes, override onRetainNonConfigurationInstance() to return an Integer containing the value of count and access that value in onCreate() by calling getLastNonConfigurationInstance() and casting it to an Integer.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
1

Here is a trick I found in a blog when I had the same issue. Try it

Create a Method getsavedstuff()

private void getsavedstuff() {
    Object mObject  = getLastNonConfigurationInstance();
}

and use it right after setContentView

public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        getsavedstuff();
}
aNi
  • 1,359
  • 11
  • 17
  • you can call getLastNonConfigurationInstance() method directly in onCreate method, how does your solution help? – Arif Nadeem Nov 22 '11 at 06:22
  • You must call getLastNonConfigurationInstance from inside the onCreate method. You are not allowed to call it from another method (such as onResume). You can call getLastNonConfigurationInstance from a method that is called inside the onCreate method – aNi Nov 22 '11 at 06:44
0

Now here is a solution that makes sense:)

public class Counter_demoActivity extends Activity {
final private static String COUNT_TITLE = "title";
private int restoredCount;
int count;
TextView tv;
@Override
public void onCreate(Bundle savedInstanceState) {
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    Button add1=(Button)findViewById(R.id.btn1);
    Button sub1=(Button)findViewById(R.id.btn2);
    tv=(TextView)findViewById(R.id.tv1);
    add1.setOnClickListener(new View.OnClickListener() {
    public void onClick(View v) {
        count++;
        tv.setText("Your Count is " + count);
    }
});
   sub1.setOnClickListener(new View.OnClickListener() {
    public void onClick(View v) {
        count--;
        tv.setText("Your Count is " +count);
    }
});
}
@Override
protected void onSaveInstanceState(Bundle outState) {
    outState.putInt(COUNT_TITLE, count);
    super.onSaveInstanceState(outState);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
     restoredCount =  savedInstanceState.getInt(COUNT_TITLE);
     count=restoredCount;
                 tv.setText("Your Count is " + restoredCount);
    super.onRestoreInstanceState(savedInstanceState);
}

}

Arif Nadeem
  • 8,524
  • 7
  • 47
  • 78
0

The problem is that you are calling setContentView inside your onConfigurationChanged.

If you overwrite onConfigurationChanged and add android:configChanges="keyboard|keyboardHidden|orientation" your activity will not be destroyed and recreated, instead onConfigurationChanged will be called. If you do not implement it super.onConfigurationChanged is called. The config changed method of the Superclass will rotate your layout without removing the values from all the fields etc. In your case the layout gets rotated correctly and after that you reset the layout yourself with calling setContentView(R.layout.main);

Janusz
  • 187,060
  • 113
  • 301
  • 369
  • Can you please have a look at my answer to my question, it works fine and preserves the value of count, but I am afraid that I am using up system resources. Is my approach correct? – Arif Nadeem Nov 23 '11 at 12:29
  • Your answer is the correct way to handle persistence of values between screen orientation changes. The android:configChanges="keyboard|keyboardHidden|orientation" solution is easier in most cases but your method should work in all cases. – Janusz Nov 23 '11 at 12:32
  • Ok thank you very much, I appreciate feedback from a valuable member of stackoverflow:), cheers:) – Arif Nadeem Nov 23 '11 at 12:34