10

On my layout, I have some buttons tho make some choices and then one button to perform a query to a database. The result of this query is shown in a ListView inside this layout.

The problem is if after I perform the query I rotate the screen, the ListView disappears and have to perform the query again.

I believe that this is happening because the activity restarts. Following the suggestions here I've added to my activity in the manifest android:configChanges="orientation|keyboardHidden" and in my code added:

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
      super.onConfigurationChanged(newConfig);
      setContentView(R.layout.mylayout);

    }

But this is not working.

Here is the complete code of my activity:

public class MyClass extends ListActivity implements OnClickListener, OnCheckedChangeListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mylayout);

        // Creates the buttons and setOnClickListener and setOnCheckedChangeListener
    }

    @Override
    public void onClick(View v) {

        // Manages the buttons and their functions

    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
        // See what group in radio group is checked
    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        // After pressing one button, a query is made and a listview is shown. 
        // This it to handle the user choice after he clicks an item on the listview

    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
      super.onConfigurationChanged(newConfig);
      setContentView(R.layout.mylayout);

    }
}

This is strange because I have some other activity like this:

public class AtoZ extends ListActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.atoz);



    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        // TODO Auto-generated method stub
        super.onListItemClick(l, v, position, id);

    }

}   

This also performs a query to the database, shows it on a ListView and then handles the user choice. If I rotate the screen, ListView still shows.

What can I do?

Community
  • 1
  • 1
Favolas
  • 6,963
  • 29
  • 75
  • 127
  • Why do you set the layout to R.layout.nutrient in the onConfigurationChanged method (instead of R.layout.mylayout as done in the onCreate method)? – Sameer Aug 29 '12 at 11:01
  • @Sameer Forgot to change that. Corrected – Favolas Aug 29 '12 at 11:04
  • How do you put the data into the ListView? Do you bind it to the DB cursor? – Sameer Aug 29 '12 at 11:15
  • @Sameer yes. `Cursor query = baseDados.getData(1,0,null); MyAdapt cursorAdapter = new MyAdapt(this, query,0); listContent.setAdapter(cursorAdapter);` On `MyAdapt` the view is bind to the cursor – Favolas Aug 29 '12 at 11:18
  • remove onConfigurationchange method if you are not changing layout. it is sufficient to write in manifiest file. – Kamal Aug 29 '12 at 11:20
  • @Kamal Removed and after screen rotation, listview dissapears – Favolas Aug 29 '12 at 11:24

5 Answers5

9

Use configChanges in your activity under manifest file.

<activity
...
...
android:configChanges="orientation|screenSize|keyboard">
</activity

This worked for me.

naamadheya
  • 1,902
  • 5
  • 21
  • 28
5

There are 2 things can solve your problems:

Solver A:

  1. Add android:configChanges="orientation|keyboardHidden" in your manifest xml file.
  2. REMOVE onConfigurationChanged(Configuration newConfig) function.

Because onCreate() is called only once every time your Activity is initialized. While your onConfigurationChanged() reloads and inflates the new view R.layout.mylayout with empty data => your list will not bound with data.

Solver B:

Move your data binding code which had been written in onCreate() to the overriding method onStart() or onResume(). I recommend that you use onStart() for your case of data binding.

You should see the Develop page Android Activity life cycle

(Update):

Because you load your listContent when clicking a search button on list item, so you have to maintain the data within activity to rebuild the list from it (for e.g: a string of search). Then in the onStart() you rebuild your list from this data.

However, it is quite strange of your logic when clicking a List's item to change the whole List itself. And notice that: onListItemClick(..) is also fired when a button on list item is clicked.

Kelvin Trinh
  • 1,248
  • 7
  • 15
  • Solver A did not work neither solver b. Put all of my code inside `onStart()` and after rotation, still the same – Favolas Aug 29 '12 at 13:57
  • Did you call `super.onListItemClick(l, v, position, id);` in your overriding method `protected void onListItemClick(..)` ? – Kelvin Trinh Aug 31 '12 at 02:43
  • 1
    you may see more for the solution at: [setRetainInstance](http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance%28boolean%29) – Kelvin Trinh Aug 31 '12 at 02:54
  • Sorry for the late check up but been away on vacancies. Yes. I've called super.onListItemClick(l, v, position, id); in my overriding method protected void onListItemClick(..). Sorry but did not understand how to use setRetainInstance. Now I what to save the listview result so when the user rotates the screen and the layout-land kicks in it shows the listview that was shown in portrait mode. – Favolas Sep 04 '12 at 11:19
  • 1
    Could you post your Manifiest xml, and some of your code which load the list; and post your Android SDK version?! I saw that you load the list view when a ListItem is clicked? this is quite strange way because at that time, the new list instance is replaced. – Kelvin Trinh Sep 05 '12 at 01:25
  • Thanks. Pasted the code that I have at http://pastebin.com/WyKPBhwm Thanks for all the help – Favolas Sep 05 '12 at 20:50
  • I didn't see `android:configChanges="orientation|keyboardHidden|screenSize"` in your xml. And notice that: `onListItemClick` is also fired with search button clicked because SrchBut is shown on list item. – Kelvin Trinh Sep 06 '12 at 02:14
  • Thanks. My buttons are on top of the list content. They are always visible on the layout.The search button is not inside a list. I forgot to say but the user choices on button one, button two and radiogroup are stored on a string array. Then, when the user presses the button 3, code inside that button goes to that string array to get the search conditions. Then the query to the database is made and it's results are shown on the listview. – Favolas Sep 06 '12 at 09:49
  • I've removed adroid:config changes because if I mantain that, when the user rotates the screen, the original layout is manteined and now I want to load a new layout. If user is on portrait mode and rotates de screen, landscaped layout it's loaded and vice-versa. – Favolas Sep 06 '12 at 09:51
3

The ListView gets recreated when you do setContentView in the onConfigurationChanged method. You need to load the data into the ListView again. if you are binding the ListView to an adapter, you need to do it in onConfigurationChanged.

Sameer
  • 4,379
  • 1
  • 23
  • 23
  • based on your comment, you need to save the cursorAdapter as a class member probably, so it can be bound to in onConfigurationChanged. – Sameer Aug 29 '12 at 11:20
  • Done that and nothing happened. Found one strange thing. in `public void onConfigurationChanged(Configuration newConfig)` typed `System.out.println("enter here");` It is not printed on logcat – Favolas Aug 29 '12 at 11:34
  • Have your read this: ... For any types of configuration changes you say that you handle there, you will receive a call to your current activity's `onConfigurationChanged(Configuration)` method instead of being restarted. If a configuration change involves any that you do not handle, however, the activity will still be restarted and `onConfigurationChanged(Configuration)` will not be called. From: [Activity dev page](http://developer.android.com/reference/android/app/Activity.html) – Kelvin Trinh Aug 31 '12 at 03:23
  • 1
    So looks like your android:configChanges setting is not taking effect. Can you post the Manifest.xml as well? – Sameer Aug 31 '12 at 06:22
  • 2
    Found the problem. You need to add "|screenSize" to configChanges setting in Manifest. http://stackoverflow.com/questions/5620033/onconfigurationchanged-not-getting-called – Sameer Aug 31 '12 at 06:54
  • @Sameer Sorry for the late check up but been away on vacancies. I've added "|screenSize" to configChanges setting in Manifest and now it works as expected. Imagine I have another layout for when the user rotates the screen (in layout-land). If, in portrait mode, user press the button and the query is made and the listview with the results of this query are shown, if he rotates the screen, the new layout kicks in thus now showing the listview. How can I save this listview so when the user rotates the screen it shows the listview? – Favolas Sep 04 '12 at 11:19
  • 1
    I believe you can't save the ListView object itself. The ListView will be recreated when the setContentView is done after configuration change. But when you bind the ListView to the cursor of the previously executed query, you should see all the rows you were seeing earlier. – Sameer Sep 04 '12 at 12:34
  • Thanks Sameer. You where very helpful – Favolas Sep 05 '12 at 20:52
2

You must to override onSaveInstanceState and onRestoreInstanceState

On the onSaveInstanceState save the ListView list on the Bundle.

On the onRestoreInstanceState, restore the list with the Bundle and recreate the adapter.

private ArrayList<String> data;

@Override
protected void onSaveInstanceState(Bundle outState) {
    outState.putSerializable("d", data);
    super.onSaveInstanceState(outState);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    if (savedInstanceState != null) {
        data = (ArrayList<String>) savedInstanceState.getSerializable("d");
        ListViewAdapter adapter = new ListViewAdapter(this, data);
        ListView listView = (ListView) findViewById(R.id.layout_listview);
        listView.setAdapter(adapter);
    }
    super.onRestoreInstanceState(savedInstanceState);
}
mabg
  • 1,894
  • 21
  • 28
-1

You will have to redo the query (if you don't save it) when you do an orientation change, because when this is done, oncreate is called again.

You could try and store the data which is in your listview, in something like shared preferences.

Anders Metnik
  • 6,096
  • 7
  • 40
  • 79
  • Thanks, but Wy do i have to do this in this case and in the class `AtoZ`, that it almost the same thing, I don't? – Favolas Aug 29 '12 at 11:16