Android listview disappears after screen rotation

17,244

Solution 1

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.

Solution 2

Use configChanges in your activity under manifest file.

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

This worked for me.

Solution 3

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.

Solution 4

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);
}
Share:
17,244
Favolas
Author by

Favolas

Updated on July 18, 2022

Comments

  • Favolas
    Favolas almost 2 years

    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?

    • Sameer
      Sameer over 11 years
      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)?
    • Favolas
      Favolas over 11 years
      @Sameer Forgot to change that. Corrected
    • Sameer
      Sameer over 11 years
      How do you put the data into the ListView? Do you bind it to the DB cursor?
    • Favolas
      Favolas over 11 years
      @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
    • Kamal
      Kamal over 11 years
      remove onConfigurationchange method if you are not changing layout. it is sufficient to write in manifiest file.
    • Favolas
      Favolas over 11 years
      @Kamal Removed and after screen rotation, listview dissapears
  • Favolas
    Favolas over 11 years
    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?
  • Sameer
    Sameer over 11 years
    based on your comment, you need to save the cursorAdapter as a class member probably, so it can be bound to in onConfigurationChanged.
  • Favolas
    Favolas over 11 years
    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
    Favolas over 11 years
    Solver A did not work neither solver b. Put all of my code inside onStart() and after rotation, still the same
  • Kelvin Trinh
    Kelvin Trinh over 11 years
    Did you call super.onListItemClick(l, v, position, id); in your overriding method protected void onListItemClick(..) ?
  • Kelvin Trinh
    Kelvin Trinh over 11 years
    you may see more for the solution at: setRetainInstance
  • Kelvin Trinh
    Kelvin Trinh over 11 years
    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
  • Sameer
    Sameer over 11 years
    So looks like your android:configChanges setting is not taking effect. Can you post the Manifest.xml as well?
  • Sameer
    Sameer over 11 years
    Found the problem. You need to add "|screenSize" to configChanges setting in Manifest. stackoverflow.com/questions/5620033/…
  • Favolas
    Favolas over 11 years
    @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
    Favolas over 11 years
    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.
  • Sameer
    Sameer over 11 years
    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.
  • Kelvin Trinh
    Kelvin Trinh over 11 years
    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.
  • Favolas
    Favolas over 11 years
    Thanks. Pasted the code that I have at pastebin.com/WyKPBhwm Thanks for all the help
  • Favolas
    Favolas over 11 years
    Thanks Sameer. You where very helpful
  • Kelvin Trinh
    Kelvin Trinh over 11 years
    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.
  • Favolas
    Favolas over 11 years
    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
    Favolas over 11 years
    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.