Android开发秘籍学习笔记(五)

来源:互联网 发布:知乎咖啡的好处与坏处 编辑:程序博客网 时间:2024/06/01 09:02

  该笔记为Android中关于适配器Adapter的使用。

Adapter的介绍:

  Adapter是用来帮助填充数据间的中间桥梁,比如通过它将数据填充到ListView,GridView,Gallery。而Android也提供了多种Adapter:ArrayAdapter,BaseAdapter,CursorAdapter,HeaderViewListAdapter, ListAdapter, ResourceCursorAdapter, SimpleAdapter, SimpleCursorAdapter, SpinnerAdapter, WrapperListAdapter.

 Adapter的用途:

  ListView,GridView等视图展示数据的格式有一定的要求,数据适配器就是建立数据源和ListView它们之间的适配关系,将数据源的数据转化成ListVIew能够ixanshide数据格式,从而将数据的来源和数据的显示进行解耦,降低了程序的耦合性,让程序更容易扩展。下面这张图就能清晰告诉你Adapter的用途


ListView的显示和缓存机制:

  由于适配器的种类繁多,不需要每种都掌握,常用的有ListView的数据填充采用的适配器BaseAdapter,在介绍如何使用BaseAdapter前,先学习下ListView的显示和缓存机制。转载自http://blog.csdn.net/deng0zhaotai/article/details/38943475

下面简单说下上图的原理:

1、如果你有几千几万甚至更多的选项(item)时,其中只有可见的项目(满屏显示的Item数目)存在内存(说的优化就是说在内存中的优化!)中,其他的在Recycler(View的缓存池)中

2、ListView先请求一个type1视图(getView)然后请求其他可见的项目。convertView在getView中是空(null)的,第一次都是为空的,只要显示过了convertView都不为空,会保存在Recycler中

3、当item1滚出屏幕,并且一个新的项目从屏幕低端上来时,ListView再请求一个type1视图。convertView此时不是空值了,它的值是item1。你只需设定新的数据然后返回convertView,不必重新创建一个视图,省去了inflate和findViewById的时间,性能就得到了优化。

Adapter模式的应用:

  接下来就结合例子讲解下BaseAdapter的使用。首先是MainActivity的布局文件---activity_main.xml
<RelativeLayout 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"    tools:context="${relativePackage}.${activityClass}" >    <ListView        android:id="@+id/lv_view"        android:layout_width="match_parent"        android:layout_height="match_parent"       /></RelativeLayout>
  一个ListView控件即可。

  再来我们需要自己构造数据源,定义一个数据源的类-----ItemBean
public class ItemBean {public  int iamgeSouceId;public String itemTitle;public String itemContent;public ItemBean(int iamgeSouceId, String itemTitle, String itemContent) {this.iamgeSouceId = iamgeSouceId;this.itemTitle = itemTitle;this.itemContent = itemContent;}}
 然后在MainActivity中给数据源赋值
List<ItemBean> itemlist = new ArrayList<ItemBean>();for (int i = 0; i < 20; i++){itemlist.add(new ItemBean(R.drawable.ic_launcher, "我是标题" + i, "我是内容" + i));}

  数据源的数据已经准备好了,接下来就是自定义适配器了。
import java.util.List;import android.annotation.SuppressLint;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;@SuppressLint("InflateParams")public class MyAdapter extends BaseAdapter {List<ItemBean> itemlist;LayoutInflater inflater;public MyAdapter(Context context,List<ItemBean> itemlist) {this.itemlist = itemlist;inflater = LayoutInflater.from(context);}@Overridepublic int getCount() {return itemlist.size();}@Overridepublic Object getItem(int position) {return itemlist.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {/*****************普通式**********************//*if(convertView == null){convertView = inflater.inflate(R.layout.item, null);}ImageView imageView = (ImageView) convertView.findViewById(R.id.item_image);TextView titleView = (TextView) convertView.findViewById(R.id.item_title);TextView contentView = (TextView) convertView.findViewById(R.id.item_content);imageView.setImageResource(itemlist.get(position).iamgeSouceId);titleView.setText(itemlist.get(position).itemTitle);contentView.setText(itemlist.get(position).itemContent);return convertView;*/ViewHolder viewHolder = new ViewHolder();if(convertView == null){convertView = inflater.inflate(R.layout.item, null);viewHolder.imageView = (ImageView) convertView.findViewById(R.id.item_image);viewHolder.titleView = (TextView) convertView.findViewById(R.id.item_title);viewHolder.contentView = (TextView) convertView.findViewById(R.id.item_content);convertView.setTag(viewHolder);        } else {        viewHolder = (ViewHolder) convertView.getTag();}viewHolder.imageView.setImageResource(itemlist.get(position).iamgeSouceId);viewHolder.titleView.setText(itemlist.get(position).itemTitle); viewHolder.contentView.setText(itemlist.get(position).itemContent);return convertView;}class ViewHolder{private ImageView imageView;private TextView titleView;private TextView contentView;}}

  可以看到我们自定义的MyAdapte继承自BaseAdapter,那么上面代码的四个函数必须重写----getCount(),getItem(),getItemId(),getView()。
其中getView()方法是BaseAdapter的精髓。有3种方式来写getView(),第一种直接创建一个新的View,完全没有利用到ListView的缓存机制,会对资源造成极大的浪费,效率极其低下,所以我这里测试都没测试。第二种是利用了ListView的convertView,它利用到了ListView的缓存机制,如果没有缓存才创建新的View,但findViewById会浪费掉系统大量的时间。最后一种利用ViewHolder,它不仅利用到ListView的缓存机制,更通过ViewHolder类来实现数据视图的缓存,避免了多次findViewById寻找控件。

最后就是给ListView添加上适配器
ListView lv_view = (ListView) findViewById(R.id.lv_view);lv_view.setAdapter(new MyAdapter(this, itemlist));

大功告成,看看效果图:


SimpleAdapter的使用:

  让我们先来看看SimpleAdapter的构造函数吧:
public SimpleAdapter (Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
  这里解释下各个参数:
  Context:          SimpleAdapter关联的View的运行环境即"上下文
  List<? extends Map<String, ?>> data:    一个Map组成的List。在列表中的每个条目对应列表中的一行,每一个map中应该包含所有在from参数中指定的键,即导入ListView或者GridView的数据源。
  resource:   一个定义列表项的布局文件的资源ID。布局文件将至少应包含那些在to中定义了的ID(子布局)
  from:          一个将被添加到Map映射上的键名
  to:     将绑定数据的视图的ID,跟from参数对应,这些应该全是TextView
public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        ListView lv = (ListView) findViewById(R.id.listView1);        String[] from = { "Text", "Button" };        int[] to = { R.id.text, R.id.button };        List<Map<String, ?>> list = new ArrayList<Map<String, ?>>();        for (int i = 0; i < 10; i++) {            Map<String, String> m = new HashMap<String, String>();            m.put("Text", "Text" + i);            m.put("Button", "Button" + i);            list.add(m);        }        SimpleAdapter adapter = new SimpleAdapter(this, list, R.layout.listitem, from, to);        lv.setAdapter(adapter);}
  来个最简单的例子,上面这个例子中定义了数据源----list,是一个Map的集合。而Map中有两个键值--“Text”和“Button”因此我们可以看到参数“from”就是这两个值组成的字符数组,而参数“to”中的int[] to = { R.id.text, R.id.button };应该是参数“source”=R.layout.listitem里两个控件的ID。


0 0
原创粉丝点击