Android Data Adapter Optimization: Efficient ViewHolder

Android Data Adapter Optimization: Efficient ViewHolder

When using Listview or GridView, a custom data adapter is often required, and getView() is generally overridden. There is a convertView parameter in this method, which is the View used to load data.

Simple but inefficient way for beginners

  1. public View getView( int position, View convertView, ViewGroup parent) {
  2.   
  3. View item= inflater.inflate(R.layout.good_list_item, null , false );
  4.         
  5. ImageView img = (ImageView) item.findViewById(R.id.img);
  6. TextView price = (TextView) item.findViewById(R.id.price);
  7. img.setImageResource(R.drawable.ic_launcher);
  8. price.setText( "$" +list.get(position).price);
  9.            
  10. return item;
  11. }

Every time you load a view, you have to recreate a lot of view objects. If a listview contains 10,000 items, this loading method will fail.

Using convertView

By using Android's Recycler mechanism and convertView to recycle View, the efficiency is substantially improved. Each creation of View is relatively time-consuming, so the judgment of convertView passed in by the getview method should be fully utilized.

  1. public View getView( int position, View convertView, ViewGroup parent) {
  2.  
  3. if (convertView == null ) {
  4. convertView = inflater.inflate(R.layout.good_list_item, null , false );
  5. }
  6. TextView tv_price = (TextView)convertView.findViewById(R.id.price)
  7. ImageView iv = (ImageView)convertView.findViewByID(R.id.img);
  8.        
  9. return convertView;
  10. }

Using ViewHolder

ViewHolder encapsulates the views that need to be cached, and setTag of convertView is used to cache them for the next call. When your listview has a diversified layout, the role of viewholder is obvious, and the efficiency is improved again. The findViewById() method of View is also time-consuming, so you need to consider calling it only once, and then use the View.getTag() method to obtain the ViewHolder object.

  1. class ViewHolder{
  2. ImageView img;
  3. TextView price;
  4. }
  5. public View getView( int position, View convertView, ViewGroup parent) {
  6. ViewHolder holder = new ViewHolder();
  7. if (convertView == null ) {
  8. convertView = inflater.inflate(R.layout.good_list_item, null , false );
  9. holder.img = (ImageView) convertView.findViewById(R.id.img);
  10. holder.price = (TextView) convertView.findViewById(R.id.price);
  11. convertView.setTag(holder);
  12. } else {
  13. holder = (ViewHolder) convertView.getTag();
  14. }
  15. //Set holder  
  16. holder.img.setImageResource(R.drawable.ic_launcher);
  17. holder.price.setText( "$" +list.get(position).price);
  18.            
  19. return convertView;
  20. }

Elegant use of ViewHolder

When using ViewHolder, you have to findViewById again and again, and add the definition of View in ViewHolder again and again. When there are many views, it feels annoying. The base-adapter-helper class library seems to solve this problem perfectly.

The design idea is to use SparseArray to store view references instead of the original ViewHolder, without declaring a large number of Views, which is concise and clear.

I also wrote a simple version of ViewHolder myself.

  1. public   class ViewHolder{
  2.    
  3. private   final SparseArray<View> views;
  4. private View convertView;
  5.   
  6. private ViewHolder(View convertView){
  7. this .views = new SparseArray<View>();
  8. this .convertView = convertView;
  9. convertView.setTag( this );
  10. }
  11.   
  12. public   static ViewHolder get(View convertView){
  13. if (convertView == null ) {
  14. return   new ViewHolder(convertView);
  15. }
  16. ViewHolder existedHolder = (ViewHolder) convertView.getTag();
  17. return stoodHolder;
  18. }
  19.   
  20. public <T extends View> T getView( int viewId) {
  21. View view = views.get(viewId);
  22. if (view == null ) {
  23. view = convertView.findViewById(viewId);
  24. views.put(viewId, view);
  25. }
  26. return (T) view;
  27. }
  28. }

It is super simple and concise to use:

  1. public View getView( int position, View convertView, ViewGroup parent) {
  2. if (convertView == null ) {
  3. convertView = LayoutInflater.from(context)
  4. .inflate(R.layout.good_list_item, null , false );
  5. }
  6.    
  7. ViewHolder mViewHolder = ViewHolder.get(convertView);
  8. TextView price = mViewHolder.getView(R.id.price);
  9. //...other getView  
  10.    
  11. return convertView;
  12. }

<<:  How to develop an Apple App of the Year? See what the founder of Replay said

>>:  Android Wear is also about to be upgraded to 5.0, and the watch face display mode is turned on

Recommend

Inventory and analysis of the top ten best-selling marketing cases in 2019!

2019 is coming to an end. Looking back on social ...

How to do user operation? Share 5 points!

one In July, I attended an operations -related co...

Will toothpaste develop "drug resistance"? Do you need to change it frequently?

Are you used to using the same toothpaste all the...

6 elements, how to trick consumers into placing orders step by step?

Our consumption behavior is 100% controlled. Why ...

In WeChat Moments: You are actually an actor

Goffman, a famous American sociologist, believes t...

5 steps to improve product conversion rate!

Double Eleven is coming soon, and many merchants ...

Star coaches teach you how to run scientifically

Course Description In life, we often hear people ...

The top ten screen-sweeping crises in 2019!

Crisis public relations summaries are made every ...