28785

Why does a ProgressBar's id need to be unique?

I declared an empty LinearLayout to which in my onCreate method I call a function that has a loop that repeats five times to inflate another layout and add it to my LinearLayout.

private void setupList() { LayoutInflater layoutInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); LinearLayout itemList = (LinearLayout) findViewById( R.id.itemList ); itemList.removeAllViews(); for ( Category category :: categories ) { View rowView = layoutInflater.inflate(R.layout.category_row, null); initializeRow( rowView, category.percentComplete ); itemList.addView( rowView ); } }

Then in my initializeRow method I initialize a TextView and ProgressBar that are in the view that I just inflated.

private void initializeRow( final View view, final int percentComplete ) { TextView topicView = ((TextView) view.findViewById(R.id.topic)); topicView.setText( category.title ); ProgressBar progressBar = (ProgressBar) view.findViewById( R.id.progressBar ); progressBar.setMax( 100 ); progressBar.setProgress( percentComplete ); TextView textView = (TextView) view.findViewById( R.id.progressText ); textView.setText( percentComplete "% Complete" ); }

The first time this activity gets created the progress bar and text view are displayed with the proper values. However if I rotate my device, the TextViews get displayed with the proper values, but all the ProgressBars show the progress that corresponds to the last ProgressBar. Why does this work when onCreate gets called initially but not when the onCreate method gets called after the device has been rotated?

I realize that all the ProgressBars have the same id. But in my code I am getting the reference to the specific ProgressBar by using the findViewById of the view that I inflated. I was able to get this working by giving each ProgressBar a unique id by calling

progressBar.setId( progressBarIds[ position ] );

in my initializeRow method. I am curious if this behavior is a result of some bug in ProgressBar or if there is some rule about layoutInflaters or ProgressBars that I do not understand.

Answer1:

The difference between onCreate and the rotation event is that in onCreate you secuentially inflate the view that has only 1 progressbar. When you call view.findViewById( R.id.progressBar ); there's only 1 possible progressbar that can be found. Then you set its value to percentComplete.

When you rotate the phone, Android destroys and creates the activity. It also then tries to restore the values of the controls/views of the activity. It saves the view's values and ids in a bundle and then tries to restore them from there. I'm suspecting that since all the progressbars have the same id, when reading the value from the bundle there's only value assigned to that id. I.e. for every control it checks its id, and tries to find the corresponding value in the bundle. Since all of them have the same id, all of them get the same value.

Consider that this is the code to save to a bundle: bundle.putInt("valueKey", integer), probably all the progressbars end up having the same key.

But regardless of how the value is stored, the id is the very mean to tell each progressbar appart from the others. How is the system to know which one is which?

Since the number of progressbars is dependant on the number of categories, you'll probably going to have to handle the activity lifecycle on your own. Probably going to implement your own onSaveInstanceState() and onRestoreInstanceState() functions so that you can store each of the category percentages in a way that you can tell them appart when you need to restore them.

Recommend

  • How to save the path of the SQLite image and then retrieve it?
  • On iOS, can you make a synchronous network request (but not on the main thread) and still get progre
  • FirebaseRecyclerAdapter doesn't recognize first layout as a position
  • Thread using for seekbar on android mediaplayer
  • Fragment setRetainInstance(true) save View properties
  • Calling super.approveSelection() within a SwingWorker
  • CSS Bundling and Internet Explorer's Limit
  • Putting progress bar inside edit text which will launch after user has entered something
  • Textview values does not update when data received from Arduino
  • Error inflating class ir.noghteh.JustifiedTextView
  • Why is this code not working? Hangman
  • How to distribute an event to all nodes in a (Wildfly) cluster?
  • UIScrollView setContentOffset: animated: not working
  • Making Cross Site Asynchronous HTTP Post from GWT Client
  • Getting IIS6 to play nice with WordPress Pretty Permalinks
  • Unix Network Programming Clarification
  • Google map in top corner left
  • Compress a file with GZipStream while maintaining its meta-data
  • Android activity accessing service's static reference before the service is ready
  • How to Cache Real-time Data?
  • Abort upload large uploads after reading headers
  • JSON response opens as a file, but I can't access it with JavaScript
  • Play WS (2.2.1): post/put large request
  • Set the selected item in dropdownlist in MVC3
  • Python CGI os.system causing malformed header
  • DomPDF {PAGE_NUM} not on first page
  • QLineEdit password safety
  • Display issues when we change from one jquery mobile page to another in firefox
  • AES padding and writing the ciphertext to a disk file
  • How to convert from System.Drawing.Color to Excel.ColorFormat in C#? Change comment color
  • Why doesn't :active or :focus work on text links in webkit? (safari & chrome)
  • Validaiting emails with Net.Mail MailAddress
  • MySQL WHERE-condition in procedure ignored
  • To display the title for the current loaction in map in iphone
  • Web-crawler for facebook in python
  • trying to dynamically update Highchart column chart but series undefined
  • How get height of the a view with gone visibility and height defined as wrap_content in xml?
  • FormattedException instead of throw new Exception(string.Format(…)) in .NET
  • Sorting a 2D array using the second column C++
  • java string with new operator and a literal