Preface Introduction:
About ListView
, we should all be very familiar with it. It is often used in Android development. Let’s review it again today.< code>How to use ListView, and some areas that need optimization attention, as well as some tips and experience in the daily development process.
ListView introduction
h3>
ListView
is a list display control provided by the Android system. It can be used to display our common list forms. Inherited from the abstract class AdapterView< /code>.
Class diagram:
form of expression
work Principle
ListView
is only used as a container (list) to load display data (the content of the red boxes above, also called item). The item in The specific data is provided by the adapter (adapter).
The adapter (adapter): as Vi ew (not only refers to ListView) and the bridge or intermediary between the data, the data is mapped to the View to be displayed. This is the simplest adapter mode and the main function of the adapter!
When the data needs to be displayed, the ListView will fetch the data from the Adapter and then load the data.
Caching principle
Previously, ListView is responsible for providing Adapter. The content is displayed one by one, and each piece of data corresponds to a item. Imagine if all the data information is loaded on the ListView and displayed, there are 100 pieces of these data added. Then the ListView will create 100 views . If there is more data, then ListView will create more views. This behavior is obviously undesirable, it will consume a lot of content.
Solution:
In order to save memory usage, ListView does not create a view for each piece of data, but uses the Recycler component method. Recycle and reuse the View.
Then How to reuse it?
We all know that the visible content of a screen is so large, so the user can see a fixed number of items at a time. If the screen can display x at a time When item (not necessarily complete), then ListView will create x+1 views; when the first item leaves the screen, the View of this item will be recycled at this time, and the View of the item that enters the screen will be prioritized Get it from the cache.
The item will only be reused after it leaves the screen completely. This is why the ListView has to create one more view than the screen needs to display: the buffered display view.
p>
There is a process for the first item to leave the screen. There will be a state where the lower part of the first item & the upper part of the X+1th item will be displayed on the screen at the same time. In this case, the cached View cannot be used. You can only continue to use the newly created view View.
Example demonstration:
If the screen is once Only 5 items can be displayed, then ListView (5+1) item views will be created; when the first item completely leaves the screen, it will be recycled to the cache for reuse. (Used to display the 7th item).
The demo image comes from the Internet:
Specific use
Introducing ListView is the same as ordinary View, just add the
ListView
control directly in the layout .File configuration information in xml
AbsListView common attributes and related methods:< /p>
Attributes Description Remarks < tbody>
android:choiceMode The selection behavior of the list: Default: none, no selection behavior Selection method: none: Do not display any selected item singleChoice: Allow single selection
multipleChoiceModel: Allow multiple selection
Use with getCheckedItemPosition, getCheckedItemCount, etc.android:drawSelectorOnTop If this attribute is set to true, the selected color of the selected list item will become the foreground color (the experiment has no effect) < /tr>
android:transcriptMode When adding new options to the specified list, whether to automatically slide to the bottom to display the new options. disabled: Cancel transcriptMode mode;
Default normal: When receiving notification of data set change, and only when the last option has been displayed on the screen, it will automatically slide to the bottom.
alwaysScroll: No matter what options are displayed in the current list, the list will automatically slide to the bottom to display the latest options.< p>XML attributes provided by ListView
XML attributes Description < th>Remarks
android:divider Set the divider of List items (available for color division , Can also be divided by picture Drawable) Do not set the dividing line between the lists, you can set the attribute to @null android: dividerHeight Used to set the height of the divider android:background attribute < td>Set the background of the list
android:entries Specify an array resource, Android will This array resource is used to generate ListView android:footerDividerEnabled If set to false, it will not be before footerView Draw the divider android:headerDividerEnabled If set to false, no longer draw the divider before headerView Article Adapter Introduction
If you use ListView, you cannot do without Adapter.
Adapter itself is an interface, the inheritance relationship of Adapter interface and its subclasses is as follows:
Introduction and use of common adapters
ArrayAdapter
Specific: use Simple, used to bind data in the form of arrays and Lists to lists as data sources, and support generic operations
Steps:
- Implement the ListView on the xml file layout
- Define the data source (list or array) in the Activity
Construct the ArrayAdapter object and set the adapter - Binding the ListView to the ArrayAdapter
- Done li>
Specific implementation:
- Add ListView
- Define the data source
ListlistData = new ArrayList<>();for(int i=0;i<20;i++){ listData.add("item数据"+i);}
- Create ArrayAdapter adapter
ArrayAdapterarrayAdapter = new ArrayAdapter<>(this,android.R.layaout.simple_list_item_1,listData); here is a brief introduction to the structure of ArrayAdapter Method, ArrayAdapter has several construction methods. The first parameter is Context and the second parameter is the layout id of the item to be added, and then the data. The data can be an array or a List. Another point to note is that if the List contains an ordinary object instead of a String, the data displayed in the item is the result of calling toString for this object.
- Binding the ArrayAdapter adapter to ListView
listView.setAdapter(arrayAdapter);Disadvantages of using ArrayAdapter
ArrayAdapter is very simple to use, which leads to very limited function implementation. Each list item can only be a TextView. The available item layouts should be simple enough!
SimpleAdapter
Compared with ArrayAdapter, it is more powerful and can bind the data of the data source to the view in the item one by one.
Steps:
- Add ListView in xml
- Implement item layout (according to actual UI requirements) li>
- Create a data source (the data source form requires List extends Map
>) - Create a SimpleAdapter adapter
- Bind SimpleAdapter adapter to ListView Medium
- Done
Specific implementation
- Add ListView in xml
- Implement item layout, here I I wrote a layout casually
Create a data source, It is very important to create a data source when using SimpleAdapter.
The fixed format of the data source is List>, generally we write List
> like this, of course, the list is stored one by one The data corresponds to the data in itme. If the layout in the item is a bit complicated, and each control in the item needs to set a different value, then the content of each layout in the item corresponds to the value in the HashMap. // For example, in the above layout, there are 4 contents to be filled, and the corresponding data source should be HashMaphashMap = new HashMap<>();hashMap.put("name","小明"); hashMap.put("age",18);hashMap.put("height",180);hashMap.put("picture",R .drawable.icon); Then there is an additional item to set up multiple such hashMaps and add them to the List to form a data source. // Specific implementation method: List > listData = new ArrayList();String[] name = new String[]{"Xiao Ming", "Xiao Hua", "Xiao Zhao", "Xiao Wang "}; String[] age = new int[]{15,16,17,18};int[] height = new int[]{180,179,174,177};int[] picture = new int[]{R.drawable.icon ,R.drawable.c,R.drawable.a,R.drawable.aa,R.drawable.ww};for(int i =0;i hashMap = new HashMap<>(); hashMap.put("name",name[i]); hashMap.put("age",age[i]); hashMap.put("height",height[i]); hashMap .put("picture",picture[i]); listData.add(hashMap);}
Create SimpleAdapter
The creation of SimpleAdapter is very easy and Fixed, because it has only one construction method
// The keys of the hashMap form a string array String[] form = new String[] {"name","age","height","picture"};// Combine the id of the view in the item layout into an array, corresponding to the form int[] to = new int[]{R.id. tv_one,R.id.tv_two,R.id.tv_three,R.id.tv_four};SimpleAdapter simpleAdapter = new SimpleAdapter(this,listData,R.layout.item_simple_adapter,form,to);< li>Bind SimpleAdapter to In ListView
listView.setAdapter(simpleAdapter);BaseAdapter
We are in the actual development process The most contacted is
BaseAdapter
. We can customize our own items to the greatest extent.Implementation steps
- Add ListView to the layout
- Implement item layout (designed according to ui)
- Create a data source
- Create your own Adapter class to inherit from BaseAdapter
- Create a custom Adapter class object
- Binding the created adapter to the ListView上
Detailed implementation steps
Add ListView to the layout (no more code, same as above
Implement item layout (still use the item layout in SimpleAdapter)
Create data source
class User{ private String name; private int age; private int height; private int picture(); get.. set... method}ListlistData = new ArrayList<>() ;for(int i=0;i<20;i++){ User user = new User(); user.setName("小明"+i); user.setAge(age); user.setHeight(height); user. setPicture(id); listData.add(user);} Create your own Adapter
// Inherited BaseAdapter must be implemented Its four methods class MyAdapter extends BaseAdapter{ // Return the number of data collections represented in the adapter // This method will be executed first (executed several times in a row), if it is 0, the subsequent methods will not be executed @ Override public int getCount() {return 0; } // Return the data item corresponding to the specified index position in the data collection // Manual call will only be executed @Override public Object getItem(int position) {return null;} // Return the row id corresponding to the specified index in the list // Manual @Override public long getItemId(int position) {return 0;} // Returns the view of the data corresponding to the specified index. @Override public View getView(int position, View convertView, ViewGroup parent) will be called multiple times. {return null; })Focus on explaining these four methods in BaseAdapter
- The reason why BaseAdapter is very Flexible, because we need to rewrite many of its methods, especially the
getView()
method, which returns any layout type we want.- Combine the above 4 methods to understand the drawing process of ListView:
- Get the length of ListView (number of items) by calling
getCount()
li>- By calling
getView()
, draw each line of the ListView one by one according to the length of the ListView- When obtaining data, use
getItem()
getItemId()
to get the data in the AdapterFocus on getView
Implementation method 1: Directly return the view corresponding to the index @Overridepublic View getView(int position,View convertView,ViewGroup parent){ View item = mInflater.inflater(R.layout.item,null) ; TextView tv = item.findViewById(R.id.tv); ImageView iv = item.findViewById(R.id.iv); Button bt = item.findViewById(R.id.bt); tv.setTextView("") ; img.setImageResource(""); .... Various settings return item;} This is the most direct way, the goal is very clear is to return the corresponding view. The same shortcoming is also very clear. It does not use ListView's reuse mechanism for items. If there are 1000 items, 1000 views will be drawn. And then findViewById will consume resources very much. Implementation method 2: Use convertView as the view cache. Use convertView as the input parameter and return parameter of getView to realize the reuse of views with the help of ListView's caching mechanism. @Overridepublic View getView(int position,View convertView,ViewGroup parent){ // Check if there is a reusable View, and if not, create a new one. // The caching principle of ListView has been introduced before, and it disappears from the page and enters the cache area View will be passed over if(convertView == null){ convertView = mInflater.inflater(R.layout.item,null);} TextView tv = convertView.findViewById(R.id.tv); ImageView iv = convertView.findViewById( R.id.iv); Button bt = convertView.findViewById(R.id.bt); tv.setTextView(""); img.setImageResource(""); .... Various settings return convertView;}// Advantages: Reduced View redrawing, and realized view reuse mechanism. Disadvantages: FindViewById every time to find component implementation mode 3: On the basis of mode 2, optimize, introduce ViewHolder to reduce findViewByIdclass ViewHolder{ TextView tv; ImageView iv; Button bt;}@Overridepublic View getView(int position,View convertView,ViewGroup parent){ ViewHolder viewHolder; if(convertView == null){ convertView = mInflater.inflater(R.layout.item,null); viewHolder = new ViewHolder(); viewHolder.tv = convertView.findViewById(R.id.tv); viewHolder.iv = convertView.fi ndViewById(R.id.iv); viewHolder.bt = convertView.findViewById(R.id.bt); // Bind viewHolder to convertView to achieve multiplexing convertView.setTag(viewHolder); }else{ viewHolder = (ViewHolder )convertView.getTag();} viewHolder.iv.set..... ..... Various settings return convertView;}// Advantages: When reusing View, there is no need to reuse findViewById again. It is the best solution for ListViewAdapter optimization summary:
some other adapters Optimization
GetView should do as little business logic processing as possible. Because getView is called very frequently.
The visible and invisible logic can be filled in the data source in advance.< /p>
Don't have a large number of objects in getView
It is better to put the created objects in ViewHolder
Load pictures, do not load pictures when sliding, it will cause ListView card Stop, you need to judge the status of ListView in the listener.
listView.setOnScrollListener(new OnScrollListenr){ @Override public void onScrollStateChanged(AbsListView lsitView,int scrollState){ if(scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING){ imageLoader.stopProcessingQueue(); }else{ // load image} }}Reference for most of this article: https://www. jianshu.com/p/4e8e4fd13cf7 Thank the author!!