注册 登录
编程论坛 Android开发

上课了讲解Android架构中的MVC

yuyu5 发布于 2017-05-31 10:29, 1754 次点击
MVC全名是Model View Controller,如图,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。

其中M层处理数据,业务逻辑等;V层处理界面的显示结果;C层起到桥梁的作用,来控制V层和M层通信以此来达到分离视图显示和业务逻辑层。

Android中的MVC
Android中界面部分也采用了当前比较流行的MVC框架,在Android中:

视图层(View)
一般采用XML文件进行界面的描述,这些XML可以理解为AndroidApp的View。使用的时候可以非常方便的引入。同时便于后期界面的修改。逻辑中与界面对应的id不变化则代码不用修改,大大增强了代码的可维护性。

控制层(Controller)
Android的控制层的重任通常落在了众多的Activity的肩上。这句话也就暗含了不要在Activity中写代码,要通过Activity交割Model业务逻辑层处理,这样做的另外一个原因是Android中的Actiivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。

模型层(Model)
我们针对业务模型,建立的数据结构和相关的类,就可以理解为AndroidApp的Model,Model是与View无关,而与业务相关的(感谢@Xander的讲解)。对数据库的操作、对网络等的操作都应该在Model里面处理,当然对业务计算等操作也是必须放在的该层的。就是应用程序中二进制的数据。

MVC代码实例
我们来看看MVC在Android开发中是怎么应用的吧!

先上界面图

 

Controller控制器&View

public class MainActivity extends ActionBarActivity implements OnWeatherListener, View.OnClickListener {

    private WeatherModel weatherModel;
    private EditText cityNOInput;
    private TextView city;
    ...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        weatherModel = new WeatherModelImpl();
        initView();
    }

    //初始化View
    private void initView() {
        cityNOInput = findView(R.id.et_city_no);
        city = findView(R.id.tv_city);
        ...
        findView(R.id.btn_go).setOnClickListener(this);
    }

    //显示结果
    public void displayResult(Weather weather) {
        WeatherInfo weatherInfo = weather.getWeatherinfo();
        city.setText(weatherInfo.getCity());
        ...
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_go:
                weatherModel.getWeather(cityNOInput.getText().toString().trim(), this);
                break;
        }
    }

    @Override
    public void onSuccess(Weather weather) {
        displayResult(weather);
    }

    @Override
    public void onError() {
        Toast.makeText(this, 获取天气信息失败, Toast.LENGTH_SHORT).show();
    }

    private T findView(int id) {
        return (T) findViewById(id);
    }
}
从上面代码可以看到,Activity持有了WeatherModel模型的对象,当用户有点击Button交互的时候,Activity作为Controller控制层读取View视图层EditTextView的数据,然后向Model模型发起数据请求,也就是调用WeatherModel对象的方法 getWeather()方法。当Model模型处理数据结束后,通过接口OnWeatherListener通知View视图层数据处理完毕,View视图层该更新界面UI了。然后View视图层调用displayResult()方法更新UI。至此,整个MVC框架流程就在Activity中体现出来了。

Model模型

来看看WeatherModelImpl代码实现

public interface WeatherModel {
    void getWeather(String cityNumber, OnWeatherListener listener);
}

................

public class WeatherModelImpl implements WeatherModel {
    /*这部分代码范例有问题,网络访问不应该在Model中,应该把网络访问换成从数据库读取*/
    @Override
    public void getWeather(String cityNumber, final OnWeatherListener listener) {

        /*数据层操作*/
        VolleyRequest.newInstance().newGsonRequest(http://www. + cityNumber + .html,
                Weather.class, new Response.Listener<weather>() {
                    @Override
                    public void onResponse(Weather weather) {
                        if (weather != null) {
                            listener.onSuccess(weather);
                        } else {
                            listener.onError();
                        }
                    }
                }, new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        listener.onError();
                    }
                });
    }
}
以上代码看出,这里设计了一个WeatherModel模型接口,然后实现了接口WeatherModelImpl类。controller控制器activity调用WeatherModelImpl类中的方法发起网络请求,然后通过实现OnWeatherListener接口来获得网络请求的结果通知View视图层更新UI 。至此,Activity就将View视图显示和Model模型数据处理隔离开了。activity担当contronller完成了model和view之间的协调作用。

至于这里为什么不直接设计成类里面的一个getWeather()方法直接请求网络数据?你考虑下这种情况:现在代码中的网络请求是使用Volley框架来实现的,如果哪天老板非要你使用Afinal框架实现网络请求,你怎么解决问题?难道是修改 getWeather()方法的实现? no no no,这样修改不仅破坏了以前的代码,而且还不利于维护, 考虑到以后代码的扩展和维护性,我们选择设计接口的方式来解决着一个问题,我们实现另外一个WeatherModelWithAfinalImpl类,继承自WeatherModel,重写里面的方法,这样不仅保留了以前的WeatherModelImpl类请求网络方式,还增加了WeatherModelWithAfinalImpl类的请求方式。Activity调用代码无需要任何修改。
0 回复
1