MCV  model view controller  模型-视图-控制写

 

android mvc项目结构 安卓mvc案例_android mvc项目结构

 

M层:适合做一些业务逻辑处理,比如数据库存取操作,网络操作,复杂的算法,耗时的任务等都在model层处理。

V层:应用层中处理数据显示的部分,XML布局可以视为V层,显示Model层的数据结果。 

C层:在Android中,Activity处理用户交互问题,因此可以认为Activity是控制器,Activity读取V视图层的数据(eg.读取当前EditText控件的数据),控制用户输入(eg.EditText控件数据的输入),并向Model发送数据请求(eg.发起网络请求等)。

 

首先来看一下MVC模式的例子,调用网络接口————藏头诗生成接口

android mvc项目结构 安卓mvc案例_android mvc项目结构_02

android mvc项目结构 安卓mvc案例_android_03

xml布局如下:

android mvc项目结构 安卓mvc案例_MVC框架模式_04

android mvc项目结构 安卓mvc案例_Group_05

1     xmlns:tools="http://schemas.android.com/tools"
  2     android:id="@+id/activity_main"
  3     android:layout_width="match_parent"
  4     android:layout_height="match_parent"
  5     android:orientation="vertical"
  6     tools:context="com.example.lesson_mvc_cangtoushi.ui.MainActivity">
  7 
  8     <RadioGroup
  9         android:id="@+id/rg_57"
 10         android:layout_width="match_parent"
 11         android:layout_height="wrap_content"
 12         android:orientation="horizontal">
 13 
 14         <RadioButton
 15             android:id="@+id/rb_5"
 16             android:layout_width="0dp"
 17             android:layout_height="wrap_content"
 18             android:layout_weight="1"
 19             android:gravity="center"
 20             android:text="五言诗" />
 21 
 22         <RadioButton
 23             android:id="@+id/rb_7"
 24             android:layout_width="0dp"
 25             android:layout_height="wrap_content"
 26             android:layout_weight="1"
 27             android:gravity="center"
 28             android:text="七言诗" />
 29     </RadioGroup>
 30 
 31     <RadioGroup
 32         android:id="@+id/rg_ct"
 33         android:layout_width="match_parent"
 34         android:layout_height="wrap_content"
 35         android:orientation="horizontal">
 36 
 37         <RadioButton
 38             android:id="@+id/rb_ct"
 39             android:layout_width="0dp"
 40             android:layout_height="wrap_content"
 41             android:layout_weight="1"
 42             android:gravity="center"
 43             android:text="藏头" />
 44 
 45         <RadioButton
 46             android:id="@+id/rb_cw"
 47             android:layout_width="0dp"
 48             android:layout_height="wrap_content"
 49             android:layout_weight="1"
 50             android:gravity="center"
 51             android:text="藏尾" />
 52 
 53         <RadioButton
 54             android:id="@+id/rb_cz"
 55             android:layout_width="0dp"
 56             android:layout_height="wrap_content"
 57             android:layout_weight="1"
 58             android:gravity="center"
 59             android:text="藏中" />
 60 
 61         <RadioButton
 62             android:id="@+id/rb_dz"
 63             android:layout_width="0dp"
 64             android:layout_height="wrap_content"
 65             android:layout_weight="1"
 66             android:gravity="center"
 67             android:text="递增" />
 68 
 69         <RadioButton
 70             android:id="@+id/rb_dj"
 71             android:layout_width="0dp"
 72             android:layout_height="wrap_content"
 73             android:layout_weight="1"
 74             android:gravity="center"
 75             android:text="递减"/>
 76 
 77     </RadioGroup>
 78 
 79     <RadioGroup
 80         android:id="@+id/rg_yy"
 81         android:layout_width="match_parent"
 82         android:layout_height="wrap_content"
 83         android:orientation="horizontal">
 84 
 85         <RadioButton
 86             android:id="@+id/rb_1y"
 87             android:layout_width="0dp"
 88             android:layout_height="wrap_content"
 89             android:layout_weight="1"
 90             android:gravity="center"
 91             android:text="双句一押" />
 92 
 93         <RadioButton
 94             android:id="@+id/rb_2y"
 95             android:layout_width="0dp"
 96             android:layout_height="wrap_content"
 97             android:layout_weight="1"
 98             android:gravity="center"
 99             android:text="双句押韵" />
100 
101         <RadioButton
102             android:id="@+id/rb_3y"
103             android:layout_width="0dp"
104             android:layout_height="wrap_content"
105             android:layout_weight="1"
106             android:gravity="center"
107             android:text="一三四押" />
108     </RadioGroup>
109     <EditText
110         android:id="@+id/et_key"
111         android:layout_width="match_parent"
112         android:layout_height="wrap_content"
113         android:hint="请输入藏头诗"/>
114     <Button
115         android:id="@+id/btn_submit"
116         android:layout_width="match_parent"
117         android:layout_height="wrap_content"
118         android:text="提交"/>
119 
120     <ScrollView
121         android:layout_width="match_parent"
122         android:layout_height="match_parent">
123         <TextView
124             android:id="@+id/tv_show"
125             android:layout_width="match_parent"
126             android:layout_height="match_parent" />
127     </ScrollView>
128 
129 
130 
131 </LinearLayout>

activity_main.xml

java代码目录结构:

android mvc项目结构 安卓mvc案例_android_06

 

首先需要一个bean,藏头诗对象原型

android mvc项目结构 安卓mvc案例_MVC框架模式_04

android mvc项目结构 安卓mvc案例_Group_05

1 public class CangTouShiBean {
 2 
 3 
 4     /**
 5      * showapi_res_code : 0
 6      * showapi_res_error :
 7      * showapi_res_body : {"ret_code":0,"list":["北风勇士马,晚水独芙蓉。吾将宝非宝,英雄徒自强。","朝骑五花马,太华三芙蓉。吾将宝非宝,天子贵文强。","请歌牵白马,菡萏金芙蓉。大位天下宝,自从冒顿强。","青丝系五马,秀出九芙蓉。迈德惟家宝,日来知自强。","北买党项马,美女夸芙蓉。河宗来献宝,十年思自强。","青丝系五马,大嫂采芙蓉。药妙灵仙宝,不独有文强。"]}
 8      */
 9 
10     private int showapi_res_code;
11     private String showapi_res_error;
12     private ShowapiResBodyBean showapi_res_body;
13 
14 
15     @Override
16     public String toString() {
17         return "CangTouShiBean{" +
18                 "showapi_res_code=" + showapi_res_code +
19                 ", showapi_res_error='" + showapi_res_error + '\'' +
20                 ", showapi_res_body=" + showapi_res_body +
21                 '}';
22     }
23 
24     public int getShowapi_res_code() {
25         return showapi_res_code;
26     }
27 
28     public void setShowapi_res_code(int showapi_res_code) {
29         this.showapi_res_code = showapi_res_code;
30     }
31 
32     public String getShowapi_res_error() {
33         return showapi_res_error;
34     }
35 
36     public void setShowapi_res_error(String showapi_res_error) {
37         this.showapi_res_error = showapi_res_error;
38     }
39 
40     public ShowapiResBodyBean getShowapi_res_body() {
41         return showapi_res_body;
42     }
43 
44     public void setShowapi_res_body(ShowapiResBodyBean showapi_res_body) {
45         this.showapi_res_body = showapi_res_body;
46     }
47 
48     public static class ShowapiResBodyBean {
49         /**
50          * ret_code : 0
51          * list : ["北风勇士马,晚水独芙蓉。吾将宝非宝,英雄徒自强。","朝骑五花马,太华三芙蓉。吾将宝非宝,天子贵文强。","请歌牵白马,菡萏金芙蓉。大位天下宝,自从冒顿强。","青丝系五马,秀出九芙蓉。迈德惟家宝,日来知自强。","北买党项马,美女夸芙蓉。河宗来献宝,十年思自强。","青丝系五马,大嫂采芙蓉。药妙灵仙宝,不独有文强。"]
52          */
53 
54         private int ret_code;
55         private List<String> list;
56 
57 
58         @Override
59         public String toString() {
60             return "ShowapiResBodyBean{" +
61                     "ret_code=" + ret_code +
62                     ", list=" + list +
63                     '}';
64         }
65 
66         public int getRet_code() {
67             return ret_code;
68         }
69 
70         public void setRet_code(int ret_code) {
71             this.ret_code = ret_code;
72         }
73 
74         public List<String> getList() {
75             return list;
76         }
77 
78         public void setList(List<String> list) {
79             this.list = list;
80         }
81     }
82 }

CangTouShiBean.java

 其次实藏头诗的接口,根据藏头诗的类型参数,请求数据,使用回调接口返回数据

android mvc项目结构 安卓mvc案例_MVC框架模式_04

android mvc项目结构 安卓mvc案例_Group_05

1 public interface BeanCallback<T> {
2 
3     void onError(String msg);
4     void onSuccess(T t);
5 }

BeanCallback.java

android mvc项目结构 安卓mvc案例_MVC框架模式_04

android mvc项目结构 安卓mvc案例_Group_05

1 public interface ICangTouShi {
2     //请求数据,需要有变化的参数
3     void doRequest(String num, String type, String yayuntype, String key,BeanCallback<CangTouShiBean> callback);
4 
5 }

ICangTouShi.java

藏头诗的model实现藏头诗的接口,并实现请求数据的方法

android mvc项目结构 安卓mvc案例_MVC框架模式_04

android mvc项目结构 安卓mvc案例_Group_05

1 public class CangTouShiModel implements ICangTouShi{
 2     @Override
 3     public void doRequest(String num, String type, String yayuntype, String key, final BeanCallback<CangTouShiBean> callback) {
 4 
 5         //请求数据
 6         //使用OkHttp
 7 
 8         OkHttpClient client = new OkHttpClient();
 9 
10         RequestBody body = new FormBody.Builder()
11                 .add("showapi_appid","27306")
12                 .add("showapi_sign","150e9206e7f542bab4affe49d73cb920")
13                 .add("num",num)
14                 .add("type",type)
15                 .add("yayuntype",yayuntype)
16                 .add("key",key).build();
17 
18         Request request = new Request.Builder()
19                 .post(body)
20                 .url("http://route.showapi.com/950-1").build();
21         Call call = client.newCall(request);
22         //异步请求,子线程
23         call.enqueue(new Callback() {
24             @Override
25             public void onFailure(Call call, IOException e) {
26                 Log.e("TAG","-----------"+e.getMessage());
27                 callback.onError(e.getMessage());
28             }
29 
30             @Override
31             public void onResponse(Call call, Response response) throws IOException {
32                 String json = response.body().string();
33                 Gson gson = new Gson();
34                 CangTouShiBean bean = gson.fromJson(json, CangTouShiBean.class);
35                 callback.onSuccess(bean);
36             }
37         });
38 
39     }
40 
41 }

CangTouShiModel.java

View层即Activity中,加载视图

android mvc项目结构 安卓mvc案例_MVC框架模式_04

android mvc项目结构 安卓mvc案例_Group_05

1 public class MainActivity extends AppCompatActivity {
  2 
  3     //逻辑判断,UI操作
  4 
  5     RadioGroup rg_57,rg_ct,rg_yy;
  6     EditText et_key;
  7     Button btn_submit;
  8     TextView tv_show;
  9 
 10     @Override
 11     protected void onCreate(Bundle savedInstanceState) {
 12         super.onCreate(savedInstanceState);
 13         setContentView(R.layout.activity_main);
 14         initView();
 15         registerListener();
 16     }
 17 
 18     private void registerListener() {
 19         //逻辑控制
 20         //实际上就只要监听提交按钮即可,因为其他的按钮只是获取数据,不需要按下后立即更改UI
 21 
 22         btn_submit.setOnClickListener(new View.OnClickListener() {
 23             @Override
 24             public void onClick(View view) {
 25                 String key = et_key.getText().toString();
 26                 if(TextUtils.isEmpty(key)){
 27                     Toast.makeText(MainActivity.this,"key不能为空",Toast.LENGTH_SHORT).show();
 28                     return;
 29                 }
 30                 String num = rg_57.getCheckedRadioButtonId()==R.id.rb_5?"5":"7";
 31                 String type = null;
 32                 switch (rg_ct.getCheckedRadioButtonId()){
 33                     case R.id.rb_ct:
 34                         type = "1";
 35                         break;
 36                     case R.id.rb_cw:
 37                         type = "2";
 38                         break;
 39                     case R.id.rb_cz:
 40                         type = "3";
 41                         break;
 42                     case R.id.rb_dz:
 43                         type = "4";
 44                         break;
 45                     case R.id.rb_dj:
 46                         type = "5";
 47                         break;
 48                 }
 49                 String yy = null;
 50                 switch (rg_yy.getCheckedRadioButtonId()){
 51                     case R.id.rb_1y:
 52                         yy="1";
 53                         break;
 54                     case R.id.rb_2y:
 55                         yy="2";
 56                         break;
 57                     case R.id.rb_3y:
 58                         yy="3";
 59                         break;
 60                 }
 61 
 62                 final ProgressDialog dialog = new ProgressDialog(MainActivity.this);
 63                 dialog.setTitle("提示");
 64                 dialog.setMessage("开始请求");
 65                 dialog.show();
 66 
 67                 //请求数据
 68                 CangTouShiModel model = new CangTouShiModel();
 69                 //OkHttp的异步请求,在子线程中
 70                 model.doRequest(num, type, yy, key, new BeanCallback<CangTouShiBean>() {
 71                     @Override
 72                     public void onError(String msg) {
 73                         runOnUiThread(new Runnable() {
 74                             @Override
 75                             public void run() {
 76                                 dialog.dismiss();
 77                                 Toast.makeText(MainActivity.this,"msg",Toast.LENGTH_SHORT).show();
 78 
 79                             }
 80                         });
 81                     }
 82 
 83                     @Override
 84                     public void onSuccess(final CangTouShiBean bean) {
 85                         runOnUiThread(new Runnable() {
 86                             @Override
 87                             public void run() {
 88                                 dialog.dismiss();
 89                                 List<String> list = bean.getShowapi_res_body().getList();
 90                                 tv_show.setText("");
 91                                 for (String s : list) {
 92                                     tv_show.append(s+"\n");
 93                                 }
 94 
 95                             }
 96                         });
 97 
 98                     }
 99                 });
100             }
101         });
102 
103     }
104 
105     private void initView() {
106         rg_57 = (RadioGroup) findViewById(R.id.rg_57);
107         rg_57.check(R.id.rb_5);
108         rg_ct = (RadioGroup) findViewById(R.id.rg_ct);
109         rg_ct.check(R.id.rb_ct);
110         rg_yy = (RadioGroup) findViewById(R.id.rg_yy);
111         rg_yy.check(R.id.rb_1y);
112         et_key = (EditText) findViewById(R.id.et_key);
113         btn_submit = (Button) findViewById(R.id.btn_submit);
114         tv_show = (TextView) findViewById(R.id.tv_show);
115 
116 
117     }
118 
119 
120 }

MainActivity.java

 

 

在MVC模式中我们发现,其实控制器Activity主要是起到解耦作用,将View视图和Model模型分离,虽然Activity起到交互作用,但是找Activity中有很多关于视图UI的显示代码,因此View视图和Activity控制器并不是完全分离的,也就是说一部分View视图和Contronller控制器Activity是绑定在一个类中的。

MVC的优点:

(1)耦合性低。所谓耦合性就是模块代码之间的关联程度。利用MVC框架使得View(视图)层和Model(模型)层可以很好的分离,这样就达到了解耦的目的,所以耦合性低,减少模块代码之间的相互影响。

(2)可扩展性好。由于耦合性低,添加需求,扩展代码就可以减少修改之前的代码,降低bug的出现率。

(3)模块职责划分明确。主要划分层M,V,C三个模块,利于代码的维护。