问题
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.
回答1:
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.
来源:https://stackoverflow.com/questions/14263665/why-does-a-progressbars-id-need-to-be-unique