Android的MVC框架

MVC是当前比较流行的框架,随便Google下,就可以发现几乎所有的应用程序开发中都采用了MVC框架,例如:.NET,Java Spring,Java Struts,PHP 。那么MVC到底是什么,为什么被广泛使用? 

简要说明下,什么是MVC。MVC (Model-View-Controller):M是指逻辑模型,V是指视图模型,C则是控制器。一个逻辑模型可以对于多种视图模型,比如一批统计数据你可以分别用柱状图、饼图来表示。一种视图模型也可以对于多种逻辑模型。使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式,而C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新,这与《设计模式》中的观察者模式是完全一样。具体详细的解析,可以去阅读百度知道中介绍的什么是MVC? 

采用MVC到底有什么好处?从用户的角度出发,用户可以根据自己的需求,选择自己合适的浏览数据的方式。比如说,对于一篇在线文档,用户可以选择以HTML网页的方式阅读,也可以选择以pdf的方式阅读。从开发者的角度,MVC把应用程序的逻辑层与界面是完全分开的,最大的好处是:界面设计人员可以直接参与到界面开发,程序员就可以把精力放在逻辑层上。而不是像以前那样,设计人员把所有的材料交给开发人员,由开发人员来实现界面。在VS 2008开发工具中设计人员就可以直接通过Silverlight来开发界面,在Eclipes工具中开发Android采用了更加简单的方法,设计人员在DroidDraw中设计界面,以XML方式保存,在Eclipes中直接打开就可以看到设计人员设计的界面。 

Android中界面部分也采用了当前比较流行的MVC框架,在Android中M就是应用程序中二进制的数据,V就是用户的界面。Android的界面直接采用XML文件保存的,界面开发变的很方便。在Android中C也是很简单的,一个Activity可以有多个界面,只需要将视图的ID传递到setContentView(),就指定了以哪个视图模型显示数据。 

在Android SDK中的数据绑定,也都是采用了与MVC框架类似的方法来显示数据。在控制层上将数据按照视图模型的要求(也就是Android SDK中的Adapter)封装就可以直接在视图模型上显示了,从而实现了数据绑定。比如显示Cursor中所有数据的ListActivity,其视图层就是一个ListView,将数据封装为ListAdapter,并传递给ListView,数据就在ListView中现实。 

目前Android中采用的MVC框架还是比较简单的,在未来还会不断完善。Android SDK如果要实现类似与MFC中视图/文档模型(View/Document Model),恐怕还需要等待一些时日,让我们拭目以待吧。  

用MVC进行重构 

感谢:http://code.google.com/p/androidbmi/wiki/BmiRefactor写的非常的好,通俗易懂而又不显啰嗦,真是恰到好处啊! 

本文仅以代码说话,主要是方便自己回想这样重构的好处,记录一下自己重构过程中的思路逻辑,更多的文字介绍请看前面那个链接! 

Step1:抽取所有界面元件的声明和定义,整合到单独一个函数findViews()中;

复制代码
 1 // 声明
 2 private Button button_calc;
 3 private EditText field_height;
 4 private EditText field_weight;
 5 private TextView view_result;
 6 private TextView view_suggest;
 7 
 8 // 定义
 9 private void findViews() {
10     button_calc = (Button) findViewById(R.id.submit);
11     field_height = (EditText) findViewById(R.id.height);
12     field_weight = (EditText) findViewById(R.id.weight);
13     view_result = (TextView) findViewById(R.id.result);
14     view_suggest = (TextView) findViewById(R.id.suggest);
15 }
复制代码

此部分即是MVC中的V:View视图。

Step2:抽取程序的逻辑(即界面元件的处理逻辑),整合到函数setListensers()中;

1 //Listen for button clicks
2 private void setListensers() {
3     button_calc.setOnClickListener(calcBMI);
4 }

此部分即是MVC中的C:Controller控制器。

接着,onCreate()就显得非常简洁、明了了:

复制代码
1 public void onCreate(Bundle savedInstanceState) {
2     super.onCreate(savedInstanceState);
3     setContentView(R.layout.main);
4 
5     findViews();
6     setListensers();
7 }
复制代码

Step3:修改按钮监听器calcBMI中相应的部分(主要是变量已经在视图部分定义了);

复制代码
 1 private OnClickListener calcBMI = new OnClickListener() {
 2     @Override
 3     public void onClick(View v) {
 4         DecimalFormat nf = new DecimalFormat("0.00");
 5 
 6         double height = Double.parseDouble(field_height.getText().toString()) / 100;
 7         double weight = Double.parseDouble(field_weight.getText().toString());
 8         double BMI = weight / (height * height);
 9 
10         // Present result
11         view_result.setText("Your BMI is " + nf.format(BMI));
12 
13         // Give health advice
14         if (BMI > 25) {
15             view_suggest.setText(R.string.advice_heavy);
16         } else if (BMI < 20) {
17             view_suggest.setText(R.string.advice_light);
18         } else {
19             view_suggest.setText(R.string.advice_average);
20         }
21     }
22 };
复制代码

Step4:修剪一下“细枝末节”;

1)        calcBMI的修改:

1 private OnClickListener calcBMI = new OnClickListener() {
2     ……
3 }

改成如下:

1 private Button.OnClickListener calcBMI = new Button.OnClickListener() {
2     ……
3 }

gasolin的解释是:

同樣是「calcBMI」 函式,在完整程式中,改將「calcBMI」 函式從原本的「OnClickListener」宣告成 「Button.OnClickListener」。這個改變有什麼差別呢?

閱讀原本的程式碼,在匯入(import)的部分可以看到,「OnClickListener」是來自於「android.view.View.OnClickListener」函式:

    import android.view.View.OnClickListener;

改成 「Button.OnClickListener」後,「Button.OnClickListener」就變成來自於「android.widget.Button」中的「OnClickListener」函式,在查閱程式時,整個「Button」與「OnClickListener」之間的關係變得更清晰。

2)        字符串统一引用XML中的描述符:

//Present result

view_result.setText("Your BMI is " + nf.format(BMI));

改成如下:

//Present result

view_result.setText(getText(R.string.bmi_result) + nf.format(BMI)); 

总之,此重构的目的无非是使程序的脉络更加清晰,即让人一眼望去,就能很容易地分辨出界面(View)应该写在哪里,程序逻辑(Controller)应该写在哪里,最终使维护和扩展代码变得更加容易!

其实,重构很简单,通读代码,感觉哪边不太爽,就改那边吧!(我目前的感受)

一个良好的代码应该是能让人感到舒服的!

附录:

1)        重构前的代码Bmi.java:

复制代码
 1 package com.demo.android.bmi;
 2 
 3 import java.text.DecimalFormat;
 4 
 5 import android.app.Activity;
 6 import android.os.Bundle;
 7 import android.view.View;
 8 import android.view.View.OnClickListener;
 9 import android.widget.Button;
10 import android.widget.EditText;
11 import android.widget.TextView;
12 
13 public class Bmi extends Activity {
14     /** Called when the activity is first created. */
15     @Override
16     public void onCreate(Bundle savedInstanceState) {
17         super.onCreate(savedInstanceState);
18         setContentView(R.layout.main);
19 
20         // Listen for button clicks
21         Button button = (Button) findViewById(R.id.submit);
22         button.setOnClickListener(calcBMI);
23     }
24 
25     private OnClickListener calcBMI = new OnClickListener() {
26         @Override
27         public void onClick(View v) {
28             DecimalFormat nf = new DecimalFormat("0.00");
29             EditText fieldheight = (EditText) findViewById(R.id.height);
30             EditText fieldweight = (EditText) findViewById(R.id.weight);
31 
32             double height = Double.parseDouble(fieldheight.getText().toString()) / 100;
33             double weight = Double.parseDouble(fieldweight.getText().toString());
34             double BMI = weight / (height * height);
35 
36             TextView result = (TextView) findViewById(R.id.result);
37             result.setText("Your BMI is " + nf.format(BMI));
38 
39             // Give health advice
40             TextView fieldsuggest = (TextView) findViewById(R.id.suggest);
41             if (BMI > 25) {
42                 fieldsuggest.setText(R.string.advice_heavy);
43             } else if (BMI < 20) {
44                 fieldsuggest.setText(R.string.advice_light);
45             } else {
46                 fieldsuggest.setText(R.string.advice_average);
47             }
48         }
49     };
50 }
复制代码

2)     重构后的代码Bmi.java:

复制代码
 1 package com.demo.android.bmi;
 2 
 3 import java.text.DecimalFormat;
 4 
 5 import android.app.Activity;
 6 import android.os.Bundle;
 7 import android.view.View;
 8 import android.widget.Button;
 9 import android.widget.EditText;
10 import android.widget.TextView;
11 
12 public class Bmi extends Activity {
13 
14     private Button button_calc;
15     private EditText field_height;
16     private EditText field_weight;
17     private TextView view_result;
18     private TextView view_suggest;
19 
20     /** Called when the activity is first created. */
21     @Override
22     public void onCreate(Bundle savedInstanceState) {
23         super.onCreate(savedInstanceState);
24         setContentView(R.layout.main);
25 
26         findViews();
27         setListensers();
28     }
29 
30     // 定义
31     private void findViews() {
32         button_calc = (Button) findViewById(R.id.submit);
33         field_height = (EditText) findViewById(R.id.height);
34         field_weight = (EditText) findViewById(R.id.weight);
35         view_result = (TextView) findViewById(R.id.result);
36         view_suggest = (TextView) findViewById(R.id.suggest);
37     }
38 
39     // Listen for button clicks
40     private void setListeners() {
41         calcbutton.setOnClickListener(calcBMI);
42     }
43 
44     private Button.OnClickListener calcBMI = new Button.OnClickListener() {
45         public void onClick(View v) {
46             DecimalFormat nf = new DecimalFormat("0.0");
47             double height = Double.parseDouble(field_height.getText().toString()) / 100;
48             double weight = Double.parseDouble(field_weight.getText().toString());
49             double BMI = weight / (height * height);
50 
51             // Present result
52             view_result.setText(getText(R.string.bmi_result) + nf.format(BMI));
53 
54             // Give health advice
55             if (BMI > 25) {
56                 view_suggest.setText(R.string.advice_heavy);
57             } else if (BMI < 20) {
58                 view_suggest.setText(R.string.advice_light);
59             } else {
60                 view_suggest.setText(R.string.advice_average);
61             }
62         }
63     };
64 }
复制代码

 

### Android MVC Framework Usage and Examples In the context of developing applications on the Android platform using an MVC (Model-View-Controller) architecture, it's important to understand how each component interacts within this design pattern. Unlike frameworks such as Spring MVC which operates under Java-based web environments[^2], Android developers must adapt these principles specifically for mobile application development. #### Model Component The model represents data structures or business logic used throughout your app. For example, consider a simple note-taking application where notes are stored locally via SQLite database: ```java public class Note { private long id; private String title; private String content; public Note(long id, String title, String content){ this.id = id; this.title = title; this.content = content; } // Getters & Setters... } ``` This `Note` object serves as part of the model layer responsible for handling information about individual notes. #### View Component Views represent what users see when interacting with apps built upon MVC patterns. In Android, views can be implemented through XML layouts combined with activities/fragments that inflate those resources at runtime. Here’s an excerpt from a layout file named `activity_main.xml`: ```xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <EditText android:id="@+id/title_edit_text" android:hint="Enter Title" android:inputType="textCapSentences" android:layout_width="match_parent" android:layout_height="wrap_content"/> <!-- More UI elements --> </LinearLayout> ``` Such code defines visual components like text fields but doesn't contain any direct interaction logic beyond defining their appearance properties. #### Controller Component Controllers act as intermediaries between models and views; they handle user inputs while updating relevant parts accordingly based on changes made either internally or externally. Within Android projects following MVC practices, Activities often play dual roles acting both as controllers managing lifecycle events alongside serving presentation purposes too. Below demonstrates basic event handling inside MainActivity.java: ```java import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.EditText; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.save_button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { EditText editTextTitle = findViewById(R.id.title_edit_text); String newTitle = editTextTitle.getText().toString(); // Assuming there exists some method addNewNote(String) DatabaseHelper.getInstance(MainActivity.this).addNewNote(newTitle,""); } }); } } ``` Here, clicking save button triggers adding a newly created note into storage managed by `DatabaseHelper`. While not explicitly mentioned in provided references, adapting concepts similar to those found within server-side implementations like Spring MVC helps structure robust client-side software solutions effectively even outside traditional desktop/web contexts.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值