Summary of various wonderful issues in android-list view
For list view, everyone must love and hate it. Based on the list view layout, as long as you are creative, you can write a variety of list views with good performance and cool interfaces. Therefore, you may encounter some problems. So I will summarize the problem here.
I. scrollview is embedded into list view. This layout is very strange. When we develop a list view, more than one screen will automatically scroll the list view because it comes with a scroll bar, if you do not believe it, you can view the source code. Haha, maybe it's a habit of thinking. Put scrollview into a listview, then the list view will display a row. Why? The nested ListView space in ScrollView cannot calculate the size of the ListView correctly. Therefore, you can use the code to calculate the size of the list based on the list items of the current ListView. Of course, there are various solutions on the Internet. I think there are two better methods.
(1) override ononMeasure () of list view. The effect is acceptable, but sometimes it fails to be tested on my machine.
public class MainListView extends ListView{ public MainListView(Context context) { // TODO Auto-generated method stub super(context); } public MainListView(Context context, AttributeSet attrs) { // TODO Auto-generated method stub super(context, attrs); } public MainListView(Context context, AttributeSet attrs, int defStyle) { // TODO Auto-generated method stub super(context, attrs, defStyle); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } }
(2) recalculate the item height of the list view, and accumulate the total height of the list view.
Public static void setListViewHeightBasedOnChildren (ListView listView) {// obtain the Adapter ListAdapter listAdapter = ListView corresponding to the listView. getAdapter (); if (listAdapter = null) {return;} int totalHeight = 0; for (int I = 0, len = listAdapter. getCount (); I <len; I ++) {// listAdapter. getCount () returns the number of data items. View listItem = listAdapter. getView (I, null, listView); listItem. measure (0, 0); // calculate the width and height of the subitem View totalHeight + = listItem. getMeasuredHeight (); // calculate the total height of all subitems} ViewGroup. layoutParams params = listView. getLayoutParams (); params. height = totalHeight + (listView. getDividerHeight () * (listAdapter. getCount ()-1); // listView. getDividerHeight () obtains the height occupied by separators between subitems. // params. the height finally shows the required height for the entire ListView. setLayoutParams (params );
The two methods are actually re-measuring the width and height of the list view.
Ii. Incorrect status of the Android ListView CheckBox
Two solutions provided by many
1: the reason for sharing convertview objects is that convetView cannot be used. Instead, the view of a new object is generated every time the getView () operation is performed. this method is probably made up of your ass.
2: Now, I will create another set to save the status of the checkBox, And then confuse and kill you. now there is a list set in the adapter that stores the checkBox status. Why do I need to save the checkBox status again?
Why does this happen?
1: Analyze viewHolder. checkBox. setOnCheckedChangeListener (new OnCheckedChangeListener ()...);
This statement adds a listener to the checkBox. If the status of the checkBox changes, the system will automatically callback the onCheckedChange () method in it.
In this article, the onCheckedChange () method writes the code that records the checkBox status after this change.
2: Analyze if (list. get (position). type = A. TYPE_CHECKED ){...}, This part of the code initializes the checkBox in the view based on the object attributes in the list set to check whether the checkBox should be selected.
3: When I slide the listView up and down, the status of the checkBox will be disordered. According to the analysis at the second point, the status of the checkBox will not be disordered no matter how it is, unless the object attribute in the list set has been changed, where has it changed?
4: In this article, there is only one place where the attribute of the checkBox object in the list set is changed, that is, the OnCheckedChangeListener () method mentioned in the first point. Is it executed?
What's going on? It's impossible. Just open a breakpoint and run it to know that it actually stopped when sliding the listView up and down.
5: This is the convertView function, because no matter how many pieces of data are displayed in the listView, only a few objects are shared. Then, each time our code re-assigns a value to the obtained object.
Ultimate solution:You only need to add the listener Method to the code that initializes the checkBox status in the view.
Iii. Analysis of misplacement, repetition, and blinking of images asynchronously loaded by Android ListView
For example, if the ListView contains 100 items and only 10 items are displayed on a screen, we know that convertView in getView () is used to reuse the View object because one Item corresponds to one View object, the ImageView control is obtained by the findViewById () of the View object. When we reuse the View object, the ImageView object is also reused. For example, if the View of 11th items reuse 1st Item View objects, the ImageView is reused at the same time. Therefore, when the image is not downloaded, this ImageView (11th items) the displayed data is reused (1st items) data.
1: The Item image is displayed repeatedly.
This duplicate display indicates that the Item in the current row displays the image of the Item in the previous row.
For example, if the ListView slides to 2nd rows, an image is asynchronously loaded, but loading is slow. During the loading process, the ListView slides to 14th rows, and the image loading ends. Rows 2nd are no longer on the screen. According to the cache principle described above, 2nd View objects may be reused by 14th rows, in this way, we can see that 14th rows show images that should belong to 2nd rows, resulting in repeated display.
2. The Item image is displayed incorrectly.
This display disorder means that a row of items displays images that do not belong to the row of items.
The reason is the same as above.
3. The Item image is flickering.
In another case described above, if 14th rows of images are soon loaded, we can see that 14th rows first display the reused 2nd rows of images, the system immediately showed that its image was overwritten, leading to flickering disorder.
Solution:
Through the above analysis, we know that the reason for confusion is asynchronous loading and Object reuse. If each getView operation can give an object an identifier, when the asynchronous loading is complete, whether the comparison mark is consistent with the ID of the Item in the current row is displayed. Otherwise, no processing is required.
Principle: first, set a Tag for the ImageView. the url of the image is set in the Tag. Then, compare the url obtained during loading with the url in the position to be loaded, if they are different, they will be loaded. If they are the same, they will not be loaded after reuse.
The above section draws on others' blogs and summarizes them. Give yourself a review.
Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.