以来来自百度百科对于MVC的解释:
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。
我一般把MVC称为Model层,View层和Controller层,为什么要称之为 "层"呢?因为Model也好,View也好,Controller也好,都不是简单的一个类或者说仅仅只是指某个东西叫Model,View,Controller,这样子就是肤浅了。我把Model描述为 " 数据的来源 ",例如数据可以从网络请求中获取,也可以从文件中获取,也可以从本地数据库中获取,等等,它一种来源方式。View描述为展示数据的方式,在Android中可以用xml文件编写,也可以用代码来编写,而Controller则描述为View和Model交互的地方。
我们来看一个MVC模式的应用:
以下代码摘自:https://blog.csdn.net/m0_37715455/article/details/81877868
①建立一个实体类(比如水果这类,添加其相应的属性)作为ListView适配器的配置类型
Fruit.java
package activitytest.example.wan.listviewtest; /** * Created by wan on 2018/8/19. */ public class Fruit { private String name;//水果名 private int imageID;//对应的图片id public Fruit(String name,int imageID){ this.name = name; this.imageID = imageID; } public String getName(){ return name; } public int getImageID(){ return imageID; } }
②用ListView的子项指定一个我们自定义的布局
fruit_item.xml
<?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"> <ImageView android:id="@+id/fruit_image" android:layout_width="100dp" android:layout_height="100dp" /> <TextView android:id="@+id/fruit_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginLeft="10dp" /> </LinearLayout>
③创建一个自定义适配器,继承ArrayAdapter,将泛型指定为Fruit类
public class FruitAdapter extends ArrayAdapter<Fruit> { private int resourceID; public FruitAdapter(Context context, int textViewResourceId,List<Fruit>objects){ super(context,textViewResourceId,objects); resourceID = textViewResourceId; } @Override public View getView(int position, View convertView, ViewGroup parent) { Fruit fruit = getItem(position);//获得当前项fruit实例 //动态加载布局文件 View view = LayoutInflater.from(getContext()).inflate(resourceID,parent,false); //找实例 ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image); TextView fruitName =(TextView)view.findViewById(R.id.fruit_name); //设置显示图片和文字 fruitImage.setImageResource(fruit.getImageID()); fruitName.setText(fruit.getName()); //返回布局 return view; } }
④修改MainActivity代码
public class MainActivity extends AppCompatActivity { //定义个容器 private List<Fruit> fruitList = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initFruits();//初始化传入数据,函数的调用 FruitAdapter adapter = new FruitAdapter(MainActivity.this, R.layout.fruit_item,fruitList); //上下文、新写的布局id、要配置的数据(ArrayList类型) //创建了FruitAdapter对象,并将它作为适配器传递给ListView ListView listView =(ListView)findViewById(R.id.list_view); listView.setAdapter(adapter);//将构造好的适配器对象传递进去 } private void initFruits(){ Fruit apple = new Fruit("Apple",R.drawable.apple); fruitList.add(apple); Fruit banana = new Fruit("Banana",R.drawable.banana); fruitList.add(banana); Fruit orange = new Fruit("Orange",R.drawable.orange); fruitList.add(orange); Fruit watermelon = new Fruit("Watermelon",R.drawable.watermelon); fruitList.add(watermelon); Fruit pear = new Fruit("Pear",R.drawable.pear); fruitList.add(pear); Fruit grape = new Fruit("Grape",R.drawable.grape); fruitList.add(grape); Fruit pineapple = new Fruit("Pineapple",R.drawable.pineapple); fruitList.add(pineapple); Fruit strewbarry = new Fruit("Strawberry",R.drawable.strawberry); fruitList.add(strewbarry); Fruit cherry = new Fruit("Cherry",R.drawable.cherry); fruitList.add(cherry); Fruit mango = new Fruit("Mango",R.drawable.mango); fruitList.add(mango); } }
来进行详解下:
View层:
很明显 fruit_item.xml是View层,用来展示视图。Fruit这个类是Model层吗?并不是,我更愿意称之为ViewData,为什么这么说?因为 Fruit的所有字段都是fruit_item.xml需要展示的数据,所以我把 fruit_item.xml与Fruit这个类一起称之为View层。
FruitAdapter是Controller吗?乍看之下,很像。其实并不是,它的作用是把ViewData和fruit_item.xml匹配起来,仅仅只是把ViewData的字段塞进fruit_item.xml而已,所以把Fruit,fruit_item.xml,FruitAdapter一起称之为View层。
Model层:
那么Model层哪一个呢?我说过了,Model描述为数据来源,是Model层在MainActivity中initFruits()方法,它创建了很多的Fruit对象,并放置于List数组中,所有说咯,这些数据,可以从文件中来,也可以从本地数据库中来,当然更可以从网络请求中来,所以很常见的是我们从网络请求,本地,数据库等获取来的数据和Fruit的字段可能并不一样,需要转换,比如网络请求中会获取大量无用的数据,或者字段也和Fruit的字段也不一样,需要转换下。如果我们从网络请求中获取数据,我们需要写Post请求;从文件中获取,我们需要写读取文件的类;所以我更愿意把数据的来源成为Model层。
Controller层:
那么Controller层是哪个呢?是MainActivity,我说过了Controler是Model层和View层交互的地方,想想看,VIew层的数据在哪里装配?在MainActivity装配,如果ListView需要设置事件监听,在哪里设置?listview.setOnItemClickListener在MainActivity中设置。
比如点击了listview的其中一个item需要重新获取数据,是不是也在MainActivity中交互?
总结:
View层的需要显示数据ViewData?从哪里来?Controller层会使用Model层来获取到所需数据。
View层所输入事件,例如listview.setOnItemClickListener,谁去相应?Controller层会去相应,执行操作。
再啰嗦几句:
往小了说:View层可以不用xml写,也可以用代码写,或者h5来写,View层也不一定就是固定的,Controller层也是一样,可以替换,Model层也是一样的,如上图可以有多个数据来源。
往大了说:View层不一定就在本地,这话说得有点绕,比如说现在不是前后端分离吗?web有自己的服务,后端也有自己的服务,web界面上点击了一个视图,会发送一个请求给后端,后端处理完自己的逻辑,返回数据,然后更新视图。那么前端就是view层;后端+json格式数据就是controller层,后端通过json格式数据来控制前端view层界面展示。这样子,view层即可以是web前端,也可以是android,ios等用来展示数据,json格式
这样子,才可以达到MVC分离的目的。