Android笔记(二十五) ListView的缓存机制与BaseAdapter
? ? ? ?之前接觸了ListView和Adapter,Adapter將數(shù)據(jù)源和View連接起來,實(shí)際應(yīng)用中,我們要顯示的數(shù)據(jù)往往有很多,而屏幕只有那么大,系統(tǒng)只能屏幕所能顯示的內(nèi)容,當(dāng)我們滑動(dòng)屏幕,會(huì)將舊的內(nèi)容放入到緩沖池中,再從緩存池中拿出新的內(nèi)容顯示出來,這就是ListView的緩存機(jī)制,這一機(jī)制可以極大的節(jié)省系統(tǒng)資源。
BaseAdapter
?????? BaseAdapter通常用于被擴(kuò)展,擴(kuò)展BaseAdapter可以對(duì)各項(xiàng)列表進(jìn)行最大限度的定制。
?????? 我們可以用自己的類去繼承BaseAdapter,然后實(shí)現(xiàn)getCount()、getItem()、getItemId()、getView()這四個(gè)方法,來完成對(duì)Adapter的定制。
?????? getCount()??? 該方法返回ListView需要顯示的數(shù)據(jù)量
?????? getItem()????? 該方法返回指定索引(position)所對(duì)應(yīng)的數(shù)據(jù)項(xiàng)
?????? getItemId()? 該方法返回對(duì)應(yīng)的索引
?????? getView()????? 該方法返回每一項(xiàng)所顯示的內(nèi)容
簡單示例:
package cn.lixyz.baseadaptertest;import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.ListView; import android.widget.Toast;import java.util.ArrayList; import java.util.List;public class MainActivity extends AppCompatActivity {List<ItemBean> itemBeanList;ListView listView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);itemBeanList = new ArrayList<ItemBean>();for (int i = 0; i < 20; i++) {ItemBean ib = new ItemBean(R.drawable.icon, "標(biāo)題" + i, "內(nèi)容" + i);itemBeanList.add(ib);}listView = (ListView) findViewById(R.id.listView);listView.setAdapter(new MyAdapter(this, itemBeanList));listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {Toast.makeText(MainActivity.this, "你選擇的是:" + position, Toast.LENGTH_SHORT).show();}});} } MainActivity.java <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><ListViewandroid:id="@+id/listView"android:layout_width="match_parent"android:layout_height="match_parent" /></LinearLayout> layout_main.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><ImageViewandroid:id="@+id/iv_icon"android:layout_width="60dp"android:layout_height="60dp"android:layout_marginLeft="10dp"android:layout_marginTop="10dp"android:src="@drawable/icon" /><TextViewandroid:id="@+id/tv_name"android:layout_width="match_parent"android:layout_height="35dp"android:layout_marginTop="10dp"android:layout_toEndOf="@+id/iv_icon"android:gravity="center"android:text="標(biāo)題"android:textSize="25dp" /><TextViewandroid:id="@+id/tv_desc"android:layout_width="match_parent"android:layout_height="25dp"android:layout_below="@+id/tv_name"android:layout_marginLeft="10dp"android:layout_toEndOf="@+id/iv_icon"android:gravity="center"android:text="內(nèi)容內(nèi)容內(nèi)容內(nèi)容" /></RelativeLayout> layout_item.xml package cn.lixyz.baseadaptertest;/*** Created by LGB on 2015/9/9.*/ public class ItemBean {public int ItemImageResid;public String ItemName;public String Itemdesc;public ItemBean(int ItemImageResid, String ItemName, String Itemdesc) {this.ItemImageResid = ItemImageResid;this.ItemName = ItemName;this.Itemdesc = Itemdesc;} } ItemBean.java package cn.lixyz.baseadaptertest;import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView;import java.util.List;/*** Created by LGB on 2015/9/9.*/ public class MyAdapter extends BaseAdapter {private List<ItemBean> list;private LayoutInflater inflater;public MyAdapter(Context context, List<ItemBean> list) {this.list = list;inflater = LayoutInflater.from(context);}//該方法返回ListView需要顯示的數(shù)據(jù)量 @Overridepublic int getCount() {return list.size();}//該方法返回指定索引(position)所對(duì)應(yīng)的數(shù)據(jù)項(xiàng) @Overridepublic Object getItem(int position) {return list.get(position);}//該方法返回對(duì)應(yīng)的索引 @Overridepublic long getItemId(int position) {return 0;}// @Overridepublic View getView(int position, View convertView, ViewGroup parent) {View view = inflater.inflate(R.layout.laytou_item, null);ImageView imageView = (ImageView) view.findViewById(R.id.iv_icon);TextView name = (TextView) view.findViewById(R.id.tv_name);TextView desc = (TextView) view.findViewById(R.id.tv_desc);imageView.setImageResource(list.get(position).ItemImageResid);name.setText(list.get(position).ItemName);desc.setText(list.get(position).Itemdesc);return view;} } MyAdapter.java運(yùn)行結(jié)果:
?
? ? ? ?上面的代碼中,我們可以看到一個(gè)ListView中的每一項(xiàng)都是我們直接使用Inflater新建并返回的,完全沒有使用到ListView提供的緩存機(jī)制
View view = inflater.inflate(R.layout.laytou_item, null); ...... return view;? ? ? ?有關(guān)inflater的內(nèi)容,可以看這里:<轉(zhuǎn)> Android LayoutInflater詳解? ? ??Android 中LayoutInflater的使用
?
? ? ? ?我們稍對(duì)代碼做一下修改:
package cn.lixyz.baseadaptertest;import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView;import java.util.List;/*** Created by LGB on 2015/9/9.*/ public class MyAdapter extends BaseAdapter {private List<ItemBean> list;private LayoutInflater inflater;public MyAdapter(Context context, List<ItemBean> list) {this.list = list;inflater = LayoutInflater.from(context);}//該方法返回ListView需要顯示的數(shù)據(jù)量 @Overridepublic int getCount() {return list.size();}//該方法返回指定索引(position)所對(duì)應(yīng)的數(shù)據(jù)項(xiàng) @Overridepublic Object getItem(int position) {return list.get(position);}//該方法返回對(duì)應(yīng)的索引 @Overridepublic long getItemId(int position) {return 0;}//該方法返回每一項(xiàng)所顯示的內(nèi)容 @Overridepublic View getView(int position, View convertView, ViewGroup parent) {if (convertView == null) {convertView = inflater.inflate(R.layout.laytou_item, null);}ImageView imageView = (ImageView) convertView.findViewById(R.id.iv_icon);TextView name = (TextView) convertView.findViewById(R.id.tv_name);TextView desc = (TextView) convertView.findViewById(R.id.tv_desc);imageView.setImageResource(list.get(position).ItemImageResid);name.setText(list.get(position).ItemName);desc.setText(list.get(position).Itemdesc);return convertView;} }? ? ? ?我們先判斷要顯示的view是否已經(jīng)存在,如果不存在,才創(chuàng)建,如果存在,就直接返回,這樣也就避免了多次重復(fù)創(chuàng)建。
? ? ? ? ?現(xiàn)在避免了多次創(chuàng)建View對(duì)象了,但是每次調(diào)用getView的時(shí)候,仍然會(huì)多次使用findViewById來創(chuàng)建組件,那么有沒有辦法可以避免在這個(gè)問題上面浪費(fèi)資源呢,這里就使用到了view的getTag和setTag,通常我們會(huì)創(chuàng)建一個(gè)ViewHolder類然后實(shí)例化,然后通過setTag的方法將這個(gè)ViewHolder對(duì)象和View連接起來
???????? 看代碼:
package cn.lixyz.baseadaptertest;import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.ListView; import android.widget.Toast;import java.util.ArrayList; import java.util.List;public class MainActivity extends AppCompatActivity {List<ItemBean> itemBeanList;ListView listView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);itemBeanList = new ArrayList<ItemBean>();for (int i = 0; i < 20; i++) {ItemBean ib = new ItemBean(R.drawable.icon, "標(biāo)題" + i, "內(nèi)容" + i);itemBeanList.add(ib);}listView = (ListView) findViewById(R.id.listView);listView.setAdapter(new MyAdapter(this, itemBeanList));listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {Toast.makeText(MainActivity.this, "你選擇的是:" + position, Toast.LENGTH_SHORT).show();}});} } MainActivity.java <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><ListViewandroid:id="@+id/listView"android:layout_width="match_parent"android:layout_height="match_parent" /></LinearLayout> activity_main.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><ImageViewandroid:id="@+id/iv_icon"android:layout_width="60dp"android:layout_height="60dp"android:layout_marginLeft="10dp"android:layout_marginTop="10dp" /><TextViewandroid:id="@+id/tv_name"android:layout_width="match_parent"android:layout_height="35dp"android:layout_marginTop="10dp"android:layout_toEndOf="@+id/iv_icon"android:gravity="center"android:text="標(biāo)題"android:textSize="25dp" /><TextViewandroid:id="@+id/tv_desc"android:layout_width="match_parent"android:layout_height="25dp"android:layout_below="@+id/tv_name"android:layout_marginLeft="10dp"android:layout_toEndOf="@+id/iv_icon"android:gravity="center"android:text="內(nèi)容內(nèi)容內(nèi)容內(nèi)容" /></RelativeLayout> layout_item.xml package cn.lixyz.baseadaptertest;/*** Created by LGB on 2015/9/9.*/ public class ItemBean {public int ItemImageResid;public String ItemName;public String Itemdesc;public ItemBean(int ItemImageResid, String ItemName, String Itemdesc) {this.ItemImageResid = ItemImageResid;this.ItemName = ItemName;this.Itemdesc = Itemdesc;} } ItemBean.java package cn.lixyz.baseadaptertest;import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView;import java.util.List;/*** Created by LGB on 2015/9/9.*/ public class MyAdapter extends BaseAdapter {private List<ItemBean> list;private LayoutInflater inflater;public MyAdapter(Context context, List<ItemBean> list) {this.list = list;inflater = LayoutInflater.from(context);}//該方法返回ListView需要顯示的數(shù)據(jù)量 @Overridepublic int getCount() {return list.size();}//該方法返回指定索引(position)所對(duì)應(yīng)的數(shù)據(jù)項(xiàng) @Overridepublic Object getItem(int position) {return list.get(position);}//該方法返回對(duì)應(yīng)的索引 @Overridepublic long getItemId(int position) {return position;}//該方法返回每一項(xiàng)所顯示的內(nèi)容 @Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder vh = null;if (convertView == null) {vh = new ViewHolder();convertView = inflater.inflate(R.layout.laytou_item, null);vh.imageView = (ImageView) convertView.findViewById(R.id.iv_icon);vh.name = (TextView) convertView.findViewById(R.id.tv_name);vh.desc = (TextView) convertView.findViewById(R.id.tv_desc);convertView.setTag(vh);} else {vh = (ViewHolder) convertView.getTag();}vh.imageView.setImageResource(list.get(position).ItemImageResid);vh.name.setText(list.get(position).ItemName);vh.desc.setText(list.get(position).Itemdesc);return convertView;}//創(chuàng)建ViewHolder,避免重復(fù)的findViewById操作浪費(fèi)資源class ViewHolder {public ImageView imageView;public TextView name;public TextView desc;} } MyAdapter.java? ? ? ? ?運(yùn)行結(jié)果是一樣的
? ? ? ? ?在上面的代碼中,我們創(chuàng)建了一個(gè)ViewHolder對(duì)象,用來保存一個(gè)Item的內(nèi)容,然后使用setTag()將View和ViewHolder對(duì)象連接起來,假如convertView不為空的話,直接使用getTag來獲取View對(duì)象,然后再給這個(gè)對(duì)象的屬性賦值(也就是給Item的組件賦值),這樣就充分利用了ListView的緩存機(jī)制,避免重復(fù)findViewById造成資源的浪費(fèi)
? ? ? ? ?總結(jié)一下使用ListView緩存機(jī)制的思路
???????? 1)創(chuàng)建Bean對(duì)象,用戶封裝數(shù)據(jù)(ItemBean)
???????? 2)在構(gòu)造方法中初始化用戶映射的數(shù)據(jù)List
???????? 3)創(chuàng)建ViewHolder類,創(chuàng)建布局映射關(guān)系
???????? 4)判斷convertView是否為空,如果為空,則創(chuàng)建,并設(shè)置tag,如果不為空,則通過getTag來去除ViewHolder
???????? 5)給ViewHolder中的控件設(shè)置數(shù)據(jù)
轉(zhuǎn)載于:https://www.cnblogs.com/xs104/p/4796423.html
總結(jié)
以上是生活随笔為你收集整理的Android笔记(二十五) ListView的缓存机制与BaseAdapter的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Java Web】Myeclipse下
- 下一篇: 设计模式二(转载)