Android 自定义Adapter

来源:互联网 发布:用php写一个 编辑:程序博客网 时间:2024/06/06 21:26
一、VC与模板概念的理解
MVC本来是存在于Desktop程序中的,M是指数据模型,V是指用户界面,C则是控制器。使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据你可以分别用柱状图、饼图来表示。C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新。

模型-视图-控制器(MVC)是Xerox PARC在八十年代为编程语言Smalltalk-80发明的一种软件设计模式,至今已被广泛使用。最近几年被推荐为Sun公司J2EE平台的设计模式,并且受到越来越多的使用 ColdFusion 和 PHP 的开发者的欢迎。模型-视图-控制器模式是一个有用的工具箱,它有很多好处,但也有一些缺点。 


二、MVC如何工作 
MVC是一个设计模式,它强制性的使应用程序的输入、处理和输出分开。使用MVC应用程序被分成三个核心部件:模型、视图、控制器。它们各自处理自己的任务。 

视图 
视图是用户看到并与之交互的界面。对老式的Web应用程序来说,视图就是由HTML元素组成的界面,在新式的Web应用程序中,HTML依旧在视图中扮演着重要的角色,但一些新的技术已层出不穷,它们包括Macromedia Flash和象XHTML,XML/XSL,WML等一些标识语言和Web services. 

如何处理应用程序的界面变得越来越有挑战性。MVC一个大的好处是它能为你的应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,不管这些数据是联机存储的还是一个雇员列表,作为视图来讲,它只是作为一种输出数据并允许用户操纵的方式。 

模型 
模型表示企业数据和业务规则。在MVC的三个部件中,模型拥有最多的处理任务。例如它可能用象EJBs和ColdFusion Components这样的构件对象来处理数据库。被模型返回的数据是中立的,就是说模型与数据格式无关,这样一个模型能为多个视图提供数据。由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。 

控制器 
控制器接受用户的输入并调用模型和视图去完成用户的需求。所以当单击Web页面中的超链接和发送HTML表单时,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后用确定用哪个视图来显示模型处理返回的数据。 

现在我们总结MVC的处理过程,首先控制器接收用户的请求,并决定应该调用哪个模型来进行处理,然后模型用业务逻辑来处理用户的请求并返回数据,最后控制器用相应的视图格式化模型返回的数据,并通过表示层呈现给用户。


自定义Adapter的实现

在xml中添加listview组件,


<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"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context=".MainActivity" >    <ListView        android:id="@+id/lv"        android:layout_width="match_parent"        android:layout_height="match_parent" >    </ListView></RelativeLayout>
然后创建自己list item模板

其中包括一个image(头像),name, age, info(黑色字体信息)。

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns: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/st_image"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:src="@drawable/wangcai" />    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="vertical" >        <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:orientation="horizontal" >            <TextView                android:id="@+id/st_name"                android:layout_width="0dp"                android:layout_height="wrap_content"                android:layout_weight="1"                android:gravity="center"                android:text="旺财"                android:textColor="#0000ff"                android:textSize="22sp" />            <TextView                android:id="@+id/st_age"                android:layout_width="0dp"                android:layout_height="wrap_content"                android:layout_weight="1"                android:gravity="center"                android:text="18"                android:textColor="#0000ff"                android:textSize="22sp" />        </LinearLayout>        <TextView            android:id="@+id/st_info"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_marginLeft="15dp"            android:layout_marginTop="30dp"            android:text="我很高兴"            android:textSize="18sp" />    </LinearLayout></LinearLayout>
下面是JAVA代码部分,开始实现自定义的Adapter。
就像使用Adapter一样,对V进行初始化,主要是findViewById。
setContentView(R.layout.activity_main);
lv = (ListView) this.findViewById(R.id.lv);
现在已经拥有了V部分,然后是创建M,即模型,使用自定义的数据填充。
               ArrayList<Person> list = new ArrayList<Person>();
自定义的数据可以是数组,map,list,链表。只要是可以通过连续标号进行增删改查的类型就可以。如果使用数组需要自己实现功能。

使用了person类型的list,就需要自定义的person类,这个类中可以实现多属性的包含。

package com.example.a18_listview;public class Person {    private int image;    private String name;    private int age;    private String info;    public String getInfo() {        return info;    }    public void setInfo(String info) {        this.info = info;    }    public int getImage() {        return image;    }    public Person(int image, String name, int age, String info) {        super();        this.image = image;        this.name = name;        this.age = age;        this.info = info;    }    public void setImage(int image) {        this.image = image;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }}
 类中定义了view list模版中需要的属性。

通过一定的方式填充model数据,这里简单的通过for循环和数组进行数据的填充。
private String names[] = { "如花", "旺财", "小翠", "小芳", "小刚", "小龙" };private int images[] = { R.drawable.ruhua, R.drawable.wangcai,R.drawable.xiaocui, R.drawable.xiaofang, R.drawable.xiaogang,R.drawable.xiaolong };private int ages[] = { 18, 19, 20, 21, 22, 23 };private String infos[] = {"我很高兴"};        ……        for (int i = 0; i < 6; i++) {list.add(new Person(images[i], names[i], ages[i], infos[0]));}
现在有了M和V ,只差C的实现。
创建自定义的Adapter,MyAdapter类。
参考Adapter系统实现,需要继承BaseAdapter类,并提示实现4个方法。
首先需要根据自己的需要实现构造函数,构造函数的参数可以根据要求定义。先看需要重写的方法吧。

第一个:获得传入的数据长度,即条目个数,需要返回list长度,或数组长度等。

@Override    public int getCount() {// 获取数量 将来要设定到lsitview控件上面的数据源的个数        // TODO Auto-generated method stub        return list.size();    }
第二个:获得条目,返回值为object表示可以返回任何类型,可以根据自己需要返回。此处返回的是list ID,也可以返回list条目中的项目,如 : return list.get(position);
@Override    public Object getItem(int position) {// 获取元素的对象(一般用在监听事件)        // TODO Auto-generated method stub        return position;    }
第三个:获得条目ID,如果在条目中定义了ID 这个属性,可以返回该值,此处,返回调用值,即list的ID 是顺序排列。

@Override    public long getItemId(int position) {// 获取元素的ID(一般用在监听事件)        // TODO Auto-generated method stub        return position;    }
第四个:填充listView视图,绘制listView视图

返回值为view类型,需要返回填充的listView模板的view类型。所以就需要在构造的时候将view传进来,但是一般layout的id容易获得,所以传入的一般是layout id,当然也可以直接传入view。
标记:构造器需要一个layout id类型参数。并用类属性保存。private int resource;
下面需要通过layout id得到layout的view类型。
View inflate = LayoutInflater.from(context).inflate(resource, null);
这句话的中需要用到context,上下文依赖关系,即是从哪个java代码包含的layout文件中查找id值(setContentView(R.layout.activity_main);),这是由于在xml中同名组件公用id,所以需要这个过程来查找id属于哪个xml。

标记:构造器需要一个context类型的参数。用于保存调用的上下文依赖关系。private Context context;

剩下的就很简单了,将list中项目的属性,依次填入listView模板中,注意,此处之需要完成一次的填充,可以使用入口参数position定位list的项目。这个方法是系统绘制时调用,由系统根据list的条目数(getCount() ),进行一次绘制。
根据position取出list中的条目。
标记:构造器需要将list传入,这个不用说,不传进来都不知道往模板上填什么。
        Person person = list.get(position);
得到条目中的每个属性。
        String name = person.getName();
        int image = person.getImage();
        int age = person.getAge();

根据layout中的组件id找到具体的组件,组件归属由前面得到的view参数获得。
        // 設定到控件上面去
        // 找控件
        TextView tv = (TextView) inflate.findViewById(R.id.st_name);
        ImageView iv = (ImageView) inflate.findViewById(R.id.st_image);
        TextView st_age = (TextView) inflate.findViewById(R.id.st_age);

将list条目的属性填写到layout模板的组件中去。
        /**
         * 设定内容
         */
        tv.setText(name);
        iv.setImageResource(image);
        st_age.setText(age + "");//age为int类型,而settext传入的参数为charsequence

最后将前面的到的view返回。
        return inflate;

方法完整代码
  /**     * getview获取listview的每一项的view视图(返回的是具体的内容)     */    @Override    public View getView(int position, View convertView, ViewGroup parent) {        // TODO Auto-generated method stub        /**         * 将布局(int)转化为view类型视图         */        View inflate = LayoutInflater.from(context).inflate(            resource, null);        // 将arraylist数据源的数据设定到控件上面        Person person = list.get(position);        String name = person.getName();        int image = person.getImage();        int age = person.getAge();        // 設定到控件上面去        // 找控件        TextView tv = (TextView) inflate.findViewById(R.id.st_name);        ImageView iv = (ImageView) inflate.findViewById(R.id.st_image);        TextView st_age = (TextView) inflate.findViewById(R.id.st_age);        /**         * 设定内容         */        tv.setText(name);        iv.setImageResource(image);        st_age.setText(age + "");//age为int类型,而settext传入的参数为charsequence        return inflate;    }
最后是完成构造器
根据前面的标记,知道要实现这4个方法,必须要的属性参数。

// 参数为 布局,数据源,    public MyAdapter(int resource, ArrayList<Person> list, Context context) {        this.resource = resource;        this.list = list;        this.context = context;    }
到这里,自己的myadapter类就完成了。回到主函数中进行MC与VC的关联,就完成了整个MVC过程。

 和系统提供的adapter一样,对model和adapter关联,通过adapter的构造器把list数据提交给adapter。
        /**         * 适配器         */        MyAdapter adapter = new MyAdapter(R.layout.mylistview_item, list,                ThirdAct.this);
将viewlist和adapter关联,通过listview的set方法将adapter传递给listview。
这样listview就知道通过什么方式填充listview中的数据,即实现的getView()方法,同时adapter中携带了list数据,也就知道需要填写多少数据。

        /**         * 将adapter适配器设定到listview中         */        lv.setAdapter(adapter);
到这里就完成自定义的adapter。

 入口函数代码:
package com.example.a18_listview;import java.util.ArrayList;import android.app.Activity;import android.os.Bundle;import android.widget.ListView;public class ThirdAct extends Activity {    private ListView lv;    private String names[] = { "如花", "旺财", "小翠", "小芳", "小刚", "小龙" };    private int images[] = { R.drawable.ruhua, R.drawable.wangcai,            R.drawable.xiaocui, R.drawable.xiaofang, R.drawable.xiaogang,            R.drawable.xiaolong };    private int ages[] = { 18, 19, 20, 21, 22, 23 };    private String infos[] = {"我很高兴"};    @Override    protected void onCreate(Bundle savedInstanceState) {        // TODO Auto-generated method stub        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        lv = (ListView) this.findViewById(R.id.lv);        /**         * 数据源         */        ArrayList<Person> list = new ArrayList<Person>();        for (int i = 0; i < 6; i++) {            list.add(new Person(images[i], names[i], ages[i], "我很高兴"));        }        /**         * 适配器         */        MyAdapter adapter = new MyAdapter(R.layout.mylistview_item, list,                ThirdAct.this);        /**         * 将adapter适配器设定到listview中         */        lv.setAdapter(adapter);    }} 











0 0
原创粉丝点击