Home  >  Article  >  Java  >  Android Talk--Usage of BaseAdapter in ListView

Android Talk--Usage of BaseAdapter in ListView

高洛峰
高洛峰Original
2016-12-13 16:41:251370browse

After developing and using various Adapters, the one I feel most comfortable using is BaseAdapter. Although it is a little more troublesome to use than other adapters, you can use it to achieve many of your favorite list layouts, such as ListView, GridView, Gallery, Spinner, etc. . It is directly inherited from the interface class Adapter. When using BaseAdapter, you need to rewrite many methods, the most important of which is getView, because this will involve issues such as ListView optimization. For other methods, please refer to the linked article

BaseAdapter and Others Adapter is a little different. Other Adapters can set data directly in their construction methods, such as

SimpleAdapter adapter = new SimpleAdapter(this, getData(), R.layout.list_item, new String[]{"img","title","info",newint[]{R.id.img, R.id.title, R.id.info}});

. But in BaseAdapter, you need to implement a class inherited from BaseAdapter and rewrite many methods in it, such as

class MyAdapter extends BaseAdapter 
    { 
        private Context context; 
        public MyAdapter(Context context) 
        { 
            this.context = context; 
        } 
        @Override 
        publicint getCount() { 
            // How many items are in the data set represented by this Adapter.(在此适配器中所代表的数据集中的条目数) 
            return0; 
        } 
 
        @Override 
        public Object getItem(int position) { 
            // Get the data item associated with the specified position in the data set.(获取数据集中与指定索引对应的数据项) 
            returnnull; 
        } 
 
        @Override 
        publiclong getItemId(int position) { 
            // Get the row id associated with the specified position in the list.(取在列表中与指定索引对应的行id) 
            return0; 
        } 
 
        @Override 
        public View getView(int position, View convertView, ViewGroup parent) { 
            // Get a View that displays the data at the specified position in the data set. 
            returnnull; 
        } 
         
    }

this There is nothing difficult in it, but this getView method must be handled carefully, which is also the most troublesome. The first type: there is no processing, and it is not recommended to write like this. If the amount of data is small, it will be fine, but if the amount of data in the list item is large, the View will be re-created every time and the resources will be set, seriously affecting the performance, so don’t use this method from the beginning

@Override 
        public View getView(int position, View convertView, ViewGroup parent) { 
            View item = mInflater.inflate(R.layout.list_item, null); 
            ImageView img = (ImageView)item.findViewById(R.id.img)  
            TextView title = (TextView)item.findViewById(R.id.title); 
            TextView info = (TextView)item.findViewById(R.id.info); 
            img.setImageResource(R.drawable.ic_launcher); 
            title.setText("Hello"); 
            info.setText("world"); 
             
            return item; 
        }

The second method ListView optimization: By caching convertView, this method of using cached contentView can determine if the View does not exist in the cache before creating the View. If it already exists, you can use the View in the cache to improve performance

public View getView(int position, View convertView, ViewGroup parent) { 
            if(convertView == null) 
            { 
                convertView = mInflater.inflate(R.layout.list_item, null); 
            } 
             
            ImageView img = (ImageView)convertView.findViewById(R.id.img)  
            TextView title = (TextView)convertView.findViewById(R.id.title); 
            TextView info = (TextView)ConvertView.findViewById(R.id.info); 
            img.setImageResource(R.drawable.ic_launcher); 
            title.setText("Hello"); 
            info.setText("world"); 
             
            return convertView; 
        }

The third ListView optimization: through convertView +ViewHolder to achieve, ViewHolder is a static class, the key benefit of using ViewHolder is to cache the view (View) that displays data, speeding up the response speed of the UI.

When we judge convertView == null , if it is empty, we will assign a value to the convertView according to the designed Item layout (XML) of the List, and generate a viewHolder to bind each View control in the convertView (XML those controls in the layout). Then use convertView's setTag to set the viewHolder to the Tag so that it can be taken out of the Tag when the system draws the ListView for the second time. (See the code below)

If convertView is not empty, convertView's getTag() will be used directly to obtain a ViewHolder.

//在外面先定义,ViewHolder静态类 
    staticclass ViewHolder 
    { 
        public ImageView img; 
        public TextView title; 
        public TextView info; 
    } 
//然后重写getView 
        @Override 
        public View getView(int position, View convertView, ViewGroup parent) { 
            ViewHolder holder; 
            if(convertView == null) 
            { 
                holder = new ViewHolder(); 
                convertView = mInflater.inflate(R.layout.list_item, null); 
                holder.img = (ImageView)item.findViewById(R.id.img)  
                holder.title = (TextView)item.findViewById(R.id.title); 
                holder.info = (TextView)item.findViewById(R.id.info); 
                convertView.setTag(holder); 
            }else 
            { 
                holder = (ViewHolder)convertView.getTag(); 
                holder.img.setImageResource(R.drawable.ic_launcher); 
                holder.title.setText("Hello"); 
                holder.info.setText("World"); 
            } 
             
            return convertView; 
        }

At this point, someone may ask what is the difference between ViewHolder static class combined with caching convertView and using convertView directly? Is it repeated?

Here, the official explanation is given

Two methods to improve Adapter

To work efficiently the adapter implemented here uses two techniques: -It reuses the convertView passed to getView() to avoid inflating View when it is not necessary

(Translation: reuse cache convertView passed to getView() method to avoid filling unnecessary views) -It uses the ViewHolder pattern to avoid calling findViewById() when it is not necessary

(Translation: Use the ViewHolder pattern to avoid unnecessary calls to findViewById(): because too many findViewById will also affect performance) The role of the ViewHolder class - The ViewHolder pattern consists in storing a data structure in the tag of the view returned by getView().This data structures contains references to the views we want to bind data to, thus avoiding calling to findViewById() every time getView() is invoked

(Translation: ViewHolder mode stores a data structure in the tag of the view returned by the getView() method. This data structure contains a reference to the view to which we

want to bind data, thereby avoiding calling getView every time () when calling findViewById())

Example 1: Use BaseAdapter to customize the ListView layout

main.xml

<?xmlversion="1.0"encoding="utf-8"?> 
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical"> 
 
    <ListView 
        android:id="@+id/lv" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:fastScrollEnabled="true" 
        /> 
 
</LinearLayout>

list_item.xml

<?xmlversion="1.0"encoding="utf-8"?> 
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="horizontal"> 
 
    <ImageView 
        android:id="@+id/img" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        /> 
    <LinearLayout  
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:orientation="vertical" 
        > 
        <TextView 
            android:id="@+id/tv" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:textSize="20sp" 
        /> 
        <TextView  
            android:id="@+id/info" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:textSize="14sp" 
            /> 
    </LinearLayout> 
     
 
</LinearLayout>

Activity

package com.loulijun.demo17; 
 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
 
import android.app.Activity; 
import android.content.Context; 
import android.os.Bundle; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.BaseAdapter; 
import android.widget.ImageView; 
import android.widget.ListView; 
import android.widget.TextView; 
 
publicclass Demo17Activity extends Activity { 
    private ListView lv; 
    private List<Map<String, Object>> data; 
    @Override 
    publicvoid onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
        lv = (ListView)findViewById(R.id.lv); 
        //获取将要绑定的数据设置到data中 
        data = getData(); 
        MyAdapter adapter = new MyAdapter(this); 
        lv.setAdapter(adapter); 
    } 
     
    private List<Map<String, Object>> getData() 
    { 
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); 
        Map<String, Object> map; 
        for(int i=0;i<10;i++) 
        { 
            map = new HashMap<String, Object>(); 
            map.put("img", R.drawable.ic_launcher); 
            map.put("title", "跆拳道"); 
            map.put("info", "快乐源于生活..."); 
            list.add(map); 
        } 
        return list; 
    } 
     
    //ViewHolder静态类 
    staticclass ViewHolder 
    { 
        public ImageView img; 
        public TextView title; 
        public TextView info; 
    } 
     
    publicclass MyAdapter extends BaseAdapter 
    {     
        private LayoutInflater mInflater = null; 
        private MyAdapter(Context context) 
        { 
            //根据context上下文加载布局,这里的是Demo17Activity本身,即this 
            this.mInflater = LayoutInflater.from(context); 
        } 
 
        @Override 
        publicint getCount() { 
            //How many items are in the data set represented by this Adapter. 
            //在此适配器中所代表的数据集中的条目数 
            return data.size(); 
        } 
 
        @Override 
        public Object getItem(int position) { 
            // Get the data item associated with the specified position in the data set. 
            //获取数据集中与指定索引对应的数据项 
            return position; 
        } 
 
        @Override 
        publiclong getItemId(int position) { 
            //Get the row id associated with the specified position in the list. 
            //获取在列表中与指定索引对应的行id 
            return position; 
        } 
         
        //Get a View that displays the data at the specified position in the data set. 
        //获取一个在数据集中指定索引的视图来显示数据 
        @Override 
        public View getView(int position, View convertView, ViewGroup parent) { 
            ViewHolder holder = null; 
            //如果缓存convertView为空,则需要创建View 
            if(convertView == null) 
            { 
                holder = new ViewHolder(); 
                //根据自定义的Item布局加载布局 
                convertView = mInflater.inflate(R.layout.list_item, null); 
                holder.img = (ImageView)convertView.findViewById(R.id.img); 
                holder.title = (TextView)convertView.findViewById(R.id.tv); 
                holder.info = (TextView)convertView.findViewById(R.id.info); 
                //将设置好的布局保存到缓存中,并将其设置在Tag里,以便后面方便取出Tag 
                convertView.setTag(holder); 
            }else 
            { 
                holder = (ViewHolder)convertView.getTag(); 
            } 
            holder.img.setBackgroundResource((Integer)data.get(position).get("img")); 
            holder.title.setText((String)data.get(position).get("title")); 
            holder.info.setText((String)data.get(position).get("info")); 
             
            return convertView; 
        } 
         
    } 
}

The running results are as follows:

Android Talk--Usage of BaseAdapter in ListViewExample 2: Apply BaseAdapter

main.xml

<?xmlversion="1.0"encoding="utf-8"?> 
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical"> 
     
    <ImageView  
        android:id="@+id/img" 
        android:layout_width="480px" 
        android:layout_height="480px" 
        android:layout_gravity="center" 
        /> 
    <Gallery  
        android:id="@+id/gallery" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:spacing="3dp" 
        android:layout_gravity="bottom" 
        /> 
 
</LinearLayout>

Activity on Gallery: getView in this part has not been optimized, and it has not been adjusted after debugging for a long time. For the time being, the most basic method is still used. I will find a special time to write about the memory leak in Gallery, because when there are a lot of image resources, it will cause out of memory errors

package com.loulijun.demo16; 
 
import android.app.Activity; 
import android.content.Context; 
import android.os.Bundle; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.AdapterView; 
import android.widget.BaseAdapter; 
import android.widget.Gallery; 
import android.widget.ImageView; 
 
publicclass Demo16Activity extends Activity { 
    private Gallery mGallery; 
    private ImageView mImg; 
    //图片数组 
    privateint[] pics = { 
            R.drawable.pic1, 
            R.drawable.pic2, 
            R.drawable.pic3, 
            R.drawable.pic4, 
            R.drawable.pic5, 
            R.drawable.pic6 
    }; 
    @Override 
    publicvoid onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
        mImg = (ImageView)findViewById(R.id.img); 
        mGallery = (Gallery)findViewById(R.id.gallery); 
        MyAdapter adapter = new MyAdapter(this); 
        mGallery.setAdapter(adapter); 
        mGallery.setOnItemClickListener(new Gallery.OnItemClickListener() 
        { 
 
            @Override 
            publicvoid onItemClick(AdapterView<?> adapter, View view, int position, 
                    long arg3) { 
                mImg.setImageResource(pics[position]); 
            } 
             
        }); 
    } 
     
    //内部类 
    class MyAdapter extends BaseAdapter 
    { 
        //用来接收传递过来的Context上下文对象 
        private Context context; 
 
        //构造函数 
        public MyAdapter(Context context) 
        { 
            this.context = context; 
        } 
        @Override 
        publicint getCount() { 
            //返回图片数组大小 
            return pics.length; 
        } 
 
        @Override 
        public Object getItem(int position) { 
            //根据选中项返回索引位置 
            return position; 
        } 
 
        @Override 
        publiclong getItemId(int position) { 
            //根据选中项id返回索引位置 
            return position; 
        } 
        //未优化的getView,这部分可以使用recycle()释放内存、或者BitmapFacotry.Options缩小,或者软引用,或者控制图片资源大小等等很多方法,找时间专门写 
        @Override 
        public View getView(int position, View convertView, ViewGroup parent) { 
            ImageView img = new ImageView(context); 
            img.setAdjustViewBounds(true); 
            img.setImageResource(pics[position]); 
            img.setScaleType(ImageView.ScaleType.FIT_XY); 
            img.setLayoutParams(new Gallery.LayoutParams(120,120)); 
             
            return img; 
        }     
    } 
}

Operation effect: The principle is the same, but there will be a difference when the layout is loaded, but Just this small difference is annoying enough

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn