资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,#,Android,应用框架,孙艳,1,框架和设计模式的区别,设计模式:,只有实例才能用代码表示;,设计重用,比框架更小的元素;,同一模式却可适用于各种应用;,设计模式是软件的知识;,小技巧,对具体问题提出解决方案,以提高代码复用率,降低耦合度。,框架:,可以用代码表示,也能直接执行或复用;,代码重用;,一个框架中往往含有一个或多个设计模式;,框架总是针对某一特定应用领域;,框架是软件;,大智慧,用来对软件设计进行分工。,2,2025/4/11 周五,1.,主流架构,MVC,(,Model-View-Controller,),MVP,(,Model-View-Presenter,),MVVM,(,Model-View-ViewModel,),3,2025/4/11 周五,MVC,的由来,MVC,(,Model-View-Controller,,模型,-,视图,-,控制器)模式是,80,年代,Smalltalk-80,出现的一种软件设计模式,后来得到了广泛的应用,其主要目的在于促进应用中模型,视图,控制器间的关注的清晰分离。,4,2025/4/11 周五,通用,MVC,Model,(模型),是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。,View,(视图),是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的。,Controller,(控制器),是应用程序中处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。,5,2025/4/11 周五,Android,中,MVC,的分工,M,层:适合做一些业务逻辑处理,比如数据库存取操作,网络操作,复杂的算法,耗时的任务等都在,model,层处理。,V,层:应用层中处理数据显示的部分,,XML,布局,可以视为,V,层,显示,Model,层的数据结果。,C,层:在,Android,中,,Activity,处理用户交互问题,因此可以认为,Activity,是控制器,,,Activity,读取,V,视图层的数据(,eg.,读取当前,EditText,控件的数据),控制用户输入(,eg.EditText,控件数据的输入),并向,Model,发送数据请求(,eg.,发起网络请求等)。,6,2025/4/11 周五,Activity,XML,布局,7,2025/4/11 周五,8,2025/4/11 周五,9,2025/4/11 周五,MVC Demo,10,2025/4/11 周五,Controller,控制器,package,com.xjp.androidmvcdemo.controller;,import,android.app.Dialog;,import,android.app.ProgressDialog;,import,android.os.Bundle;,import,android.support.v7.app.ActionBarActivity;,import,android.view.View;,import,android.widget.EditText;,import,android.widget.TextView;,import,android.widget.Toast;,import,com.xjp.androidmvcdemo.R;,import,com.xjp.androidmvcdemo.entity.Weather;,import,com.xjp.androidmvcdemo.entity.WeatherInfo;,import,com.xjp.androidmvcdemo.model.OnWeatherListener;,import,com.xjp.androidmvcdemo.model.WeatherModel;,import,com.xjp.androidmvcdemo.model.WeatherModelImpl;,public,class,MainActivity,extends,ActionBarActivity,implements,OnWeatherListener,View.OnClickListener,private,WeatherModel weatherModel;,private,Dialog loadingDialog;,private,EditText cityNOInput;,private,TextView city;,private,TextView cityNO;,private,TextView temp;,private,TextView wd;,private,TextView ws;,private,TextView sd;,private,TextView wse;,private,TextView time;,private,TextView njd;,11,2025/4/11 周五,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);,cityNO=findView(R.id.tv_city_no);,temp=findView(R.id.tv_temp);,wd=findView(R.id.tv_WD);,ws=findView(R.id.tv_WS);,sd=findView(R.id.tv_SD);,wse=findView(R.id.tv_WSE);,time=findView(R.id.tv_time);,njd=findView(R.id.tv_njd);,findView(R.id.btn_go).setOnClickListener(,this,);,loadingDialog=,new,ProgressDialog(,this,);,loadingDialog.setTitle(加载天气中.);,12,2025/4/11 周五,/*,*显示结果,*,*param weather,*/,public,void,displayResult(Weather weather),WeatherInfo weatherInfo=weather.getWeatherinfo();,city.setText(weatherInfo.getCity();,cityNO.setText(weatherInfo.getCityid();,temp.setText(weatherInfo.getTemp();,wd.setText(weatherInfo.getWD();,ws.setText(weatherInfo.getWS();,sd.setText(weatherInfo.getSD();,wse.setText(weatherInfo.getWSE();,time.setText(weatherInfo.getTime();,njd.setText(weatherInfo.getNjd();,/*,*隐藏进度对话框,*/,public,void,hideLoadingDialog(),loadingDialog.dismiss();,Override,public,void,onClick(View v),switch,(v.getId(),case,R.id.btn_go:,loadingDialog.show();,weatherModel.getWeather(cityNOInput.getText().toString().trim(),this,);,break,;,这里为什么不直接设计成类里面的一个,getWeather,()方法直接请求网络数据?,13,2025/4/11 周五,Override,public,void,onSuccess(Weather weather),hideLoadingDialog();,displayResult(weather);,Override,public,void,onError(),hideLoadingDialog();,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,中体现出来了。,14,2025/4/11 周五,Model,模型,package,com.xjp.androidmvcdemo.model;,public,interface,WeatherModel,void,getWeather(String cityNumber,OnWeatherListener listener);,.,package,com.xjp.androidmvcdemo.model;,import,com.android.volley.Response;,import,com.android.volley.VolleyError;,import,com.xjp.androidmvcdemo.entity.Weather;,import,com.xjp.androidmvcdemo.volley.VolleyRequest;,public,class,WeatherModelImpl,implements,WeatherModel,Override,public,void,getWeather(String cityNumber,final,OnWeatherListener listener),/*数据层操作*/,VolleyRequest.newInstance().newGsonRequest(http:,/+cityNumber+.html,Weather.,class,new,Response.Listener(),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();,);,15,2025/4/11 周五,MVC,的优缺点,缺点:,没有明确的定义,不适合小型,中等规模的应用程序,增加系统结构和实现的复杂性,视图与控制器间的过于紧密的连接,视图对模型数据的低效率访问,一般高级的界面工具或构造器不支持模式,优点:,耦合性低,重用性高,生命周期成本低,部署快,可维护性高,有利软件工程化管理,16,2025/4/11 周五,MVP,由来,随着UI创建技术的功能日益增强,UI层也履行着越来越多的职责。为了更好地细分视图(View)与模型(Model)的功能,让View专注于处理数据的可视化以及与用户的交互,同时让Model只关系数据的处理,基于MVC概念的MVP(Model-View-Presenter)模式应运而生。,17,2025/4/11 周五,在MVP模式里通常包含4个要素,View,:负责绘制UI元素、与用户进行交互(在Android中体现为Activity);,View interface,:需要View实现的接口,View通过View interface与Presenter进行交互,降低耦合,方便进行单元测试;,Model,:负责存储、检索、操纵数据(有时也实现一个Model interface用来降低耦合),;,Presenter,:作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。,18,2025/4/11 周五,Model,模型,package,com.xjp.androidmvcdemo.model;,public,interface,WeatherModel,void,getWeather(String cityNumber,OnWeatherListener listener);,.,package,com.xjp.androidmvcdemo.model;,import,com.android.volley.Response;,import,com.android.volley.VolleyError;,import,com.xjp.androidmvcdemo.entity.Weather;,import,com.xjp.androidmvcdemo.volley.VolleyRequest;,public,class,WeatherModelImpl,implements,WeatherModel,Override,public,void,getWeather(String cityNumber,final,OnWeatherListener listener),/*数据层操作*/,VolleyRequest.newInstance().newGsonRequest(http:,/+cityNumber+.html,Weather.,class,new,Response.Listener(),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();,);,19,2025/4/11 周五,Presenter,控制器,public,interface,WeatherPresenter,void,getWeather(String cityNO);,.,public,interface,OnWeatherListener,void,onSuccess(Weather weather);,void,onError();,.,package,org.rocko.demos.mvp.presenter.impl;,import,org.rocko.demos.mvp.model.WeatherModel;,import,org.rocko.demos.mvp.model.entity.Weather;,import,org.rocko.demos.mvp.model.impl.WeatherModelImpl;,import,org.rocko.demos.mvp.presenter.OnWeatherListener;,import,org.rocko.demos.mvp.presenter.WeatherPresenter;,import,org.rocko.demos.mvp.ui.view.WeatherView;,public,class,WeatherPresenterImpl,implements,WeatherPresenter,OnWeatherListener,/*Presenter作为中间层,持有View和Model的引用*/,private,WeatherView weatherView;,private,WeatherModel weatherModel;,public,WeatherPresenterImpl(WeatherView weatherView),this,.weatherView=weatherView;,weatherModel=,new,WeatherModelImpl();,20,2025/4/11 周五,Override,public,void,getWeather(String cityNO),weatherView.showLoading();,weatherModel.getWeather(cityNO,this,);,Override,public,void,onSuccess(Weather weather),weatherView.hideLoading();,weatherView.setWeatherInfo(weather);,Override,public,void,onError(),weatherView.hideLoading();,weatherView.showError();,从代码中我们可以看到,Presenter,控制器同时持有,WeatherModel,和,WeatherView,对象且实现了,OnWeatherListener,接口取回,Model,模型数据,因此,,WeatherPresenterImpl,向,WeatherModel,发送数据请求,然后通过,OnWeatherListener,接口实现获取请求结果,在将结果通过接口,WeatherView,把数据显示到,Activity,担当的,View,视图中。从而达到彻底将,Model,和,View,完全分离,试想在这种情况下,如果你需要修改,Model,是完全不会影响,View,视图代码的修改的,同理,修改,View,视图层的时候,也完全无需修改,Model,层。相当于,Model,和,View,互相不知道对方的存在,都是通过中间控制器,Presenter,来传达通信。,21,2025/4/11 周五,View,视图,public,interface,WeatherView,void,showLoading();,void,hideLoading();,void,showError();,void,setWeatherInfo(Weather weather);,public,class,WeatherActivity,extends,BaseActivity,implements,WeatherView,View.OnClickListener,private,Dialog loadingDialog;,private,EditText cityNOInput;,private,TextView city;,private,TextView cityNO;,private,TextView temp;,private,TextView wd;,private,TextView ws;,private,TextView sd;,private,TextView wse;,private,TextView time;,private,TextView njd;,private,WeatherPresenter weatherPresenter;,Override,protected,void,onCreate(Bundle savedInstanceState),super,.onCreate(savedInstanceState);,setContentView(R.layout.activity_main);,init();,22,2025/4/11 周五,private,void,init(),cityNOInput=findView(R.id.et_city_no);,city=findView(R.id.tv_city);,cityNO=findView(R.id.tv_city_no);,temp=findView(R.id.tv_temp);,wd=findView(R.id.tv_WD);,ws=findView(R.id.tv_WS);,sd=findView(R.id.tv_SD);,wse=findView(R.id.tv_WSE);,time=findView(R.id.tv_time);,njd=findView(R.id.tv_njd);,findView(R.id.btn_go).setOnClickListener(,this,);,weatherPresenter=,new,WeatherPresenterImpl(,this,);,/传入WeatherView,loadingDialog=,new,ProgressDialog(,this,);,loadingDialog.setTitle(,加载天气中.,);,Override,public,void,onClick(View v),switch,(v.getId(),case,R.id.btn_go:,weatherPresenter.getWeather(cityNOInput.getText().toString().trim();,break,;,23,2025/4/11 周五,Override,public,void,showLoading(),loadingDialog.show();,Override,public,void,hideLoading(),loadingDialog.dismiss();,Override,public,void,showError(),/Do something,Toast.makeText(getApplicationContext(),error,Toast.LENGTH_SHORT).show();,Override,public,void,setWeatherInfo(Weather weather),WeatherInfo info=weather.getWeatherinfo();,city.setText(info.getCity();,cityNO.setText(info.getCityid();,temp.setText(info.getTemp();,wd.setText(info.getWD();,ws.setText(info.getWS();,sd.setText(info.getSD();,wse.setText(info.getWS();,time.setText(info.getTemp();,njd.setText(info.getNjd();,24,2025/4/11 周五,为什么使用,MVP,模式,?,在,Android,开发中,,Activity,并不是一个标准的,MVC,模式中的,Controller,,,它 的首要职责是加载应用的布局和初始化用户界面,并接受并处理来自用户的操作请求,进而作出响应。随着界面及其逻辑的复杂度不断提升,,Activity,类的 职责不断增加,以致变得庞大臃肿。当我们将其中复杂的逻辑处理移至另外的一个类(,Presneter,)中时,,Activity,其实就是,MVP,模式中,View,,它负责,UI,元素的初始化,建立,UI,元素与,Presenter,的关联(,Listener,之类),同时自己也会处理一些简单的逻辑(复杂的逻辑交由,Presenter,处理),.,25,2025/4/11 周五,MVP,与,MVC,的差异,MVP,模式:,View,不直接与,Model,交互,,而是通过与,Presenter,交互来与,Model,间接交互,;,Presenter,与,View,的交互是通过接口来进行的,更有利于添加单元测试,;,通常,View,与,Presenter,是一对一的,但复杂的,View,可能绑定多个,Presenter,来处理逻辑,.,MVC,模式:,View,可以与,Model,直接交互,;,Controller,是基于行为的,并且可以被多个,View,共享,;,可以负责决定显示哪个,View.,26,2025/4/11 周五,27,2025/4/11 周五,Rosen,项目应用代码,以,iPod,为例,工程间依赖关系为:,RosenIpod,RosenIpodController RosenCommonUI RosenCommon,为什么提取,Common,?,便于维护,所有应用相同的部分只需要改动一处代码。,2.,界面与逻辑为什么分开?,使得界面与逻辑解耦,如果不强制分开,可能会导致,UI,的代码杂糅逻辑代码,结果就是“,解不断理还乱,”;,能够支持,UI,灵活变更,能够修改逻辑代码却不会影响,UI,。,28,2025/4/11 周五,我们的“,MVC,”,View(Activity),Controller,Module(DataSource),View,:对应于,Android,的,Activity,;,Controller,用于将,action,转换为,message,发送给,DataSource,处理;,Module,处理应用程序数据逻辑的部分。,XXObserver,用于监听,controller,返回给,view,的结果,ViewObserver,ControllerObserver,29,2025/4/11 周五,UML,基础,继承,指的是一个类(称为子类、子接口)继承另外的一个类(称为父类、父接口)的功能,并可以增加它自己的新功能的能力,继承是类与类或者接口与接口之间最常见的关系;在Java中此类关系通过关键字extends明确标识,在设计时一般没有争议性;,30,2025/4/11 周五,实现,指的是一个,class,类实现,interface,接口(可以是多个)的功能;实现是类与接口之间最常见的关系;在,Java,中此类关系通过关键字,implements,明确标识,在设计时一般没有争议性;,31,2025/4/11 周五,依赖,可以简单的理解,就是一个类,A,使用到了另一个类,B,,而这种使用关系是具有偶然性的、临时性的、非常弱的,但是,B,类的变化会影响到,A,;比如,某人要过河,需要借用一条船,,此时人与船之间的关系就是依赖;表现在代码层面,为类,B,作为参数被类,A,在某个,method,方法中使用;,32,2025/4/11 周五,关联,他体现的是两个类、或者类与接口之间语义级别的一种强依赖关系,比如,我和我的朋友,;这种关系比依赖更强、不存在依赖关系的偶然性、关系也不是临时性的,一般是长期性的,而且双方的关系一般是,平等,的、关联可以是单向、双向的;表现在代码层面,为被关联类,B,以类属性的形式出现在关联类,A,中,也可能是关联类,A,引用了一个类型为被关联类,B,的全局变量;,33,2025/4/11 周五,聚合,是关联关系的一种特例,他体现的是整体与部分、拥有的关系,即,has-a,的关系,此时整体与部分之间是可分离的,他们可以具有各自的生命周期,部分可以属于多个整体对象,也可以为多个整体对象共享;比如,计算机与,CPU,、,公司与员工,的关系等;表现在代码层面,和关联关系是一致的,只能从语义级别来区分;,34,2025/4/11 周五,组合,组合也是关联关系的一种特例,他体现的是一种,contains-a,的关系,这种关系比聚合更强,也称为强聚合;他同样体现整体与部分间的关系,但此时整体与部分是不可分的,整体的生命周期结束也就意味着部分的生命周期结束;比如,你和你的大脑,;表现在代码层面,和关联关系是一致的,只能从语义级别来区分;,35,2025/4/11 周五,RosenTitleBar,View,TitleBarView,Controller,TitleBarController,Module,TitleBarDataSource,36,2025/4/11 周五,TitleBar,的类图关系,37,2025/4/11 周五,TitleBarView,拥有,:,TitleBarInterface,TitleBarController,拥有:,List,BaseDataSourceInterface,TitleBarDataSource,拥有:,List,38,2025/4/11 周五,public interface BaseControllerInterface,void addObserver(T observer);,void removeObserver(T observer);,public interface ControllerObserver,public void onDataChanged(BaseMessage msg);,public interface BaseDataSourceInterface,void addControllerObserver(ControllerObserver observer);,void removeControllerObserver(ControllerObserver observer);,void handleMessage(BaseMessage msg,boolean isCanCanceled);,39,2025/4/11 周五,public interface XXObserver,(,TitleBarObserver,),public void onXXResp(BaseMessage msg);,public interface XXInterface extends BaseControllerInterface,(,XXInterface,),void XXReq();,40,2025/4/11 周五,对应关系,View,:,Controller,(单例),1,:,n,一个,View,对应多个不同的,Controller,n,:,1,多个不同的,View,对应同一个,Controller,1,:,1,一个,View,对应一个,Controller,Controller,:,DataSource,(非单例),1,:,1,一个,Controller,对应一个,DataSource,除了,Controller,以外不允许任何类调用,DataSource,DataSource,不允许逆向调用,Controller,41,2025/4/11 周五,为什么,Controller,与,DataSource,分开?,1.BaseDataSource,中实现了异步任务处理,目的是防止在主线程中做耗时的操作;,2.Controller,中可以保存临时数据,,DataSource,只做异步数据获取或数据处理,职责单一。,42,2025/4/11 周五,BroadcastReceiver,位于何处?,其数据只对一个,DataSource,有用,则可以注册于,DataSource,,通过,receiveMessage,(,BaseMessage,)将数据上报给,Controller,如果是单独的,Receiver,类(必须为单例),接收到的数据传给,Controller,处理,1,、,notifyUI,;,2,、,sendMessage,()给,DataSource,处理,当应用未启动时也需要监听则注册为静态广播,这种情况应该位于,ui,层,43,2025/4/11 周五,谢谢!,良好的代码结构和编码规范离不开大家的努力,共勉!,44,2025/4/11 周五,
展开阅读全文