首页 > 代码库 > MVC ListView 随笔

MVC ListView 随笔

1.什么是MVC

      MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑----摘自百度百科。

M:model:指的是用来封装信息的对象。
V:view:用来显示model中封装的信息的组件。
C:controller:用来控制model中的信息怎么输出到view中的。

在android中最典型的MVC就是listview的显示
M:model指你要显示的数据,如封装数据的cursor,array等等
V:view:就是listView用来显示封装好的数据
C:controller:就是adaptor,用来控制数据如何向listview中显示,如arrayadaptor,cursoradaptor等等

      MVC可以使程序耦合性降低,视图层和业务层分离,这样就允许更改视图层代码而不用重新编译模型和控制器代码,同样,一个应用的业务流程或者业务规则的改变只需要改动MVC的模型层即可.同时可以让代码复用性提高,由于已经将数据和业务规则从表示层分开,所以可以最大化的重用代码了。


2.MVC与Android SDK

      MVC的基本原理就是通过Controller连接View和Model。也就是说,当View中显示的数据发生变化时,就会通知Controller,而不是直接通知Model,这时Controller接到View的通知后,会在Model中采取相应的动作来修改数据,使用MVC模式可以将数据和显示部分分离,这样修改一方时不会影响另一方,更有利于程序的维护。

      在Android SDK中使用MVC的组件非常多,例如,列表控件ListView,GridView,Spinner等都采用MVC模式与数据交互,在Android中MVC中的V就是组件,M就代表着各种数据源,C代表Adapter类,包括BaseAdapter,SimpleAdapter,SimpleCursorAdapter,ArrayAdapter,CursorAdapter等。他们分别对应不同的数据源,这些Adapter都需要使用getView方法返回当前列表项显示的View对象,当Model发生改变的时候调用BaseAdapter.notifyDataSetChanged方法通知组件数据发生变化,这时Adapter会调用getView方法重新显示内容。总之无论是数据还是组件发生变化,都要通过Adapter这个桥梁来达到同步的目的。


3.Adapter的简单使用

     1.ArrayAdapter

String data[] =new String[]{"A","B","C","D","E","F"};
listView = (ListView) findViewById(R.id.listView);
ArrayAdapter<String> adapter =new ArrayAdapter<String>(this, 
			android.R.layout.simple_list_item_1, data);
listView.setAdapter(adapter);

代码很简单,效果也很简单,事实上ArrayAdapter有多种构造方法,稍稍改变一下第二个参数就可以得到带单选,多选,勾选等效果的ListView。

如:android.R.layout.simple_list_item_checked:

还有android.R.layout.simple_list_item_multiple_choice多选框   ,android.R.layout.simple_list_item_single_choice单选框 等。当然这些都需要使用listView.setChoiceMode();来设置单选多选,若不设置单选多选将不会生效。

注意:其中第二个参数可以自定义一个layout,但是这个layout必须要有TextView控件。


      2.SimpleAdapter

List<Map<String,Object>> data =http://www.mamicode.com/new ArrayList>();>
R.layout.item
<?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="wrap_content"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
         />

</LinearLayout>

效果图如下:

public SimpleAdapter (Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
构造函数
参数
context   关联SimpleAdapter运行着的视图的上下文。
data      一个Map的列表。在列表中的每个条目对应列表中的一行
resource  一个定义列表项目的视图布局的资源唯一标识。布局文件将至少应包含哪些在to中定义了的名称。
from      一个将被添加到Map上关联每一个项目的列名称的列表
to        列表每一子View中需要数据的控件的ID,与from一一对应


       3.自定义Adapter

BaseAdapter有4个抽象方法:getItem,getItemId,getCount和getView,其中前2个返回Object和long类型的值。不一定要在这2个方法中编写具体的代码,一般用这2个方法返回当前列表的对象和列表项的ID,getCount返回列表数据总数,getView返回当前列表显示的View对象,一般重点复写这个方法。

package org.goodev.squaregrid;

import java.util.ArrayList;
import java.util.List;

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;

public class GridAdapter extends BaseAdapter{
    public static class Item{
        public String text;
        public int resId;
    }
    private List<Item> mItems = new ArrayList<GridAdapter.Item>();
    private Context mContext;
    public GridAdapter(Context context) {
        //测试数据
    	//为了方便起见数据直接写在这里
        for (int i = 0; i < 50; i++) {
            Item object = new Item();
            object.text = "Text "+i;
            object.resId = R.drawable.icon;
            mItems.add(object);
        }
        mContext = context;
    }
    @Override
    public int getCount() {
        return mItems.size();
    }

    @Override
    public Object getItem(int position) {
        return mItems.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if(convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(R.layout.item, null);
        }
        ImageView image = (ImageView) convertView.findViewById(R.id.icon);
        TextView text = (TextView) convertView.findViewById(R.id.text);
        Item item = (Item) getItem(position);
        image.setImageResource(item.resId);
        text.setText(item.text);
        return convertView;
    }
}
注:
BaseAdapter是一个抽象类,继承它需要实现较多的方法,所以也就具有较高的灵活性。
ArrayAdapter支持泛型操作,通常需要实现getView方法,特殊情况下(结合数据row id),为了让ui事件相应处理方便点最好重写getItemId;。
SimpleAdapter类构造方法的第四个参数from表示Map对象中的key。

SimpleCursorAdapter和CursorAdapter就不多做介绍了。