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 =new ArrayList<Map<String,Object>>(); for(int i ='A';i<='F';i++) { Map<String,Object> temp = new HashMap<String, Object>(); temp.put("imge", R.drawable.ic_launcher); temp.put("text", String.valueOf((char)i)); data.add(temp); } listView = (ListView) findViewById(R.id.listView); SimpleAdapter adapter =new SimpleAdapter(this, data, R.layout.item, new String[]{"imge","text"}, new int[]{R.id.imageView,R.id.textView}); listView.setAdapter(adapter);
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就不多做介绍了。