框架模式笔记:MVC 与MVP框架(完)
来源:互联网 发布:淘宝包邮退货邮费规则 编辑:程序博客网 时间:2024/06/07 03:21
注:部分内容参考了http://blog.csdn.net/jdsjlzx/article/details/51174396
MVC模块分析:
M:model,模型层,数据源,Android中一般对应JAVABean,DAO,本地的数据文件或者网络获取的数据内容。
V:view,视图层,负责数据的显示,在Android中 视图层一般由XML担任。
C:controller,控制层,控制数据如何显示在view上,在Android中一般由Activity担任。
框架图:
MVC之间的联系:
比如你的界面有一个按钮,按下这个按钮去网络上下载一个文件,这个按钮是view层的,是使用xml来写的,而那些和网络连接相关的代码写在其他类里。比如你可以写一个专门的networkHelper类,这个就是model层,那怎么连接这两层呢?是通过button.setOnClickListener()这个函数,这个函数就写在了activity中,对应于controller层
优点:
- 容易理解
- 逻辑清晰,分工明确(前端专注界面,后端专注业务逻辑)
- 松耦合
缺点:
由于MVC将程序分为3个部分,意味着同一个工程将包含更多的文件。对于小型项目,MVC会导致更大的工作量和更高的复杂性。
实例:
M:data.xml
<?xml version="1.0" encoding="utf-8"?><resources> <string-array name="data"> <item>AAAAA</item> <item>BB</item> <item>CCC</item> <item>VVVV</item> <item>DDDD</item> <item>FGGGGGGGGGGGGGG</item> <item>FDSGSD</item> <item>GDDF</item> <item>SDSSSSSSSSSS</item> <item>SSSS</item> </string-array></resources>
V:list_item.xml
<?xml version="1.0" encoding="utf-8"?><TextView xmlns:android="http://schemas.android.com/apk/res/android" android:padding="20dp" android:textColor="#0F0" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
C:MainActivity
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ListView listView = new ListView(this); listView.setBackgroundColor(Color.WHITE); setContentView(listView); String[] s = getResources().getStringArray(R.array.data); ArrayAdapter adapter = new ArrayAdapter(this, R.layout.list_item, s); listView.setAdapter(adapter); }}
MVC的思考
MVC存在缺陷:问题就在于xml作为view层,控制能力实在太弱了,你想去动态的改变一个页面的背景,或者动态的隐藏/显示一个按钮,这些都没办法在xml中做,只能把代码写在activity中,造成了activity既是controller层,又是view层的这样一个窘境。大家回想一下自己写的代码,如果是一个逻辑很复杂的页面,activity或者fragment是不是动辄上千行呢?这样不仅写起来麻烦,维护起来更是噩梦。
MVC还有一个重要的缺陷,大家看上面那幅图,view层和model层是相互可知的,这意味着两层之间存在耦合,耦合对于一个大型程序来说是非常致命的,因为这表示开发,测试,维护都需要花大量的精力
MVP模块分析
P:Presenter
交互中间人:Presenter主要作为沟通View与Model的桥梁,它从Model层检索数据后,通过接口的形式将View层需要的数据返回给View层,使得View与Model之间没有耦合,也将业务逻辑从View角色上抽离出来。
V:View
用户界面:View通常是指Activity、Fragment或者某个View控件。它含有一个Presenter成员变量。通常View需要实现一个逻辑接口,将View上的操作转交给Presenter进行实现,最后,Presenter 调用View逻辑接口将结果返回给View元素。
M:Model
数据的存取:Model 角色主要是提供数据的存取功能。Presenter 需要通过Model层存储、获取数据,Model就像一个数据仓库。更直白的说,Model是封装了数据库DAO或者网络获取数据的角色,或者两种数据方式获取的集合。
框架图:
MVC VS MVP:
从图中就可以看出,最明显的差别就是view层和model层不再相互可知,完全的解耦,取而代之的presenter层充当了桥梁的作用,用于操作view层发出的事件传递到presenter层中,presenter层去操作model层,并且将数据返回给view层,整个过程中view层和model层完全没有联系。看到这里大家可能会问,虽然view层和model层解耦了,但是view层和presenter层不是耦合在一起了吗?其实不是的,对于view层和presenter层的通信,我们是可以通过接口实现的,具体的意思就是说我们的activity,fragment可以去实现实现定义好的接口,而在对应的presenter中通过接口调用方法。不仅如此,我们还可以编写测试用的View,模拟用户的各种操作,从而实现对Presenter的测试。这就解决了MVC模式中测试,维护难的问题。
MVP案例:
参考自鸿洋MVP
结构图:
Model层:(对应于Activity,负责View的绘制以及与用户交互)
UserBean:
public class UserBean { private String name; private String pass; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPass() { return pass; } public void setPass(String pass) { this.pass = pass; }}
业务逻辑部分(biz就是business哦,我也是才知道-。-)
接口类
public interface ILogin { void login(String name,String pass,ILoginListener listener);}
监听
public interface ILoginListener { void LoginSuccess(UserBean user); void LoginFailed();}
接口实现类
public class LoginImpl implements ILogin { @Override public void login(final String name, final String pass, final ILoginListener listener) { Thread thread = new Thread() { @Override public void run() { try { Thread.sleep(1500); } catch (InterruptedException e) { e.printStackTrace(); } if (name.equals("chj") && "123".equals(pass )) { UserBean user = new UserBean(); user.setName(name); user.setPass(pass); listener.LoginSuccess(user); } else { listener.LoginFailed(); } } }; thread.start(); }}
这个Listener我也是看了好久才知道作用的,在V层调用P层的接口的时候,P层的接口其实调用的是M层的接口,P层调用接口时会触发监听器,M层通过回调告诉P调用的结果,然后由P调用V封装的接口做UI动作更新。(如果刚开始看不懂,请看过整体后再看)
M层完工!
View层:(业务逻辑和实体模型)
先定义View的接口类,接口主要看UI要进行哪些更新,比如如何和用户交互,如何优化操作,如何进行与P层进行逻辑交互等等。
public interface IView_Login { public String getName(); public String getPass(); public void hideProcess(); public void showProcess(); public void clearName(); public void clearPass(); public void showSuccess(); public void showFailed(); public void enablebtns(); public void disablebtns();}
根据接口类完成Activity:
public class MainActivity extends AppCompatActivity implements IView_Login { Button btnLogin, btnClear; ProgressBar progress_login; EditText edtpass, edtname; LoginPresenter logPresenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); btnClear.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { logPresenter.clear(); } }); btnLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { logPresenter.Login(); } }); } private void initView() { logPresenter = new LoginPresenter(this); btnClear = (Button) findViewById(R.id.btnclear); btnLogin = (Button) findViewById(R.id.btnlogin); progress_login = (ProgressBar) findViewById(R.id.progress_login); edtname = (EditText) findViewById(R.id.edtname); edtpass = (EditText) findViewById(R.id.edtpass); } @Override public String getName() { return edtname.getText().toString().trim(); } @Override public String getPass() { return edtpass.getText().toString().trim(); } @Override public void hideProcess() { progress_login.setVisibility(View.INVISIBLE); } @Override public void showProcess() { progress_login.setVisibility(View.VISIBLE); } @Override public void clearName() { edtname.setText(""); } @Override public void clearPass() { edtpass.setText(""); } @Override public void showSuccess() { Toast.makeText(this, "login success", Toast.LENGTH_SHORT).show(); } @Override public void showFailed() { Toast.makeText(this, "login failed", Toast.LENGTH_SHORT).show(); } @Override public void enablebtns() { btnClear.setEnabled(true); btnLogin.setEnabled(true); } @Override public void disablebtns() { btnClear.setEnabled(false); btnLogin.setEnabled(false); }}
click事件是需要与Presenter交互的,它就决定了Presenter要有哪些接口。
View层完工!
Presenter层:(负责完成View于Model间的交互)
Presenter是用作Model和View之间交互的桥梁,那么应该有什么方法呢?主要看View的需求
public class LoginPresenter { ILogin iLogin; IView_Login iView_login; Handler myHandler = new Handler(); public LoginPresenter(IView_Login iView_login) { this.iView_login = iView_login; this.iLogin = new LoginImpl(); } public void Login(){ iView_login.disablebtns(); iView_login.showProcess(); iLogin.login(iView_login.getName(), iView_login.getPass(), new ILoginListener() { @Override public void LoginSuccess(UserBean user) { myHandler.post(new Runnable() { @Override public void run() { iView_login.hideProcess(); iView_login.showSuccess(); iView_login.enablebtns(); } }); } @Override public void LoginFailed() { myHandler.post(new Runnable() { @Override public void run() { iView_login.hideProcess(); iView_login.showFailed(); iView_login.enablebtns(); } }); } }); } public void clear(){ iView_login.clearName(); iView_login.clearPass(); }}
presenter完工!
另外贴上xml吧
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.caihuijian.test.view.MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:orientation="horizontal"> <Button android:id="@+id/btnlogin" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_weight="1" android:text="Login" /> <Button android:id="@+id/btnclear" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_weight="1" android:text="Clear" /> </LinearLayout> <EditText android:id="@+id/edtname" android:layout_width="200dp" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_alignParentTop="true" android:layout_marginRight="50dp" android:hint="@string/hint_name" android:inputType="textPersonName" /> <EditText android:id="@+id/edtpass" android:layout_width="200dp" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_below="@+id/edtname" android:layout_marginRight="50dp" android:hint="@string/hint_pass" android:inputType="numberPassword" /> <TextView android:id="@+id/uname" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/edtname" android:layout_alignBottom="@+id/edtname" android:layout_alignParentStart="true" android:text="@string/uname" /> <TextView android:id="@+id/upass" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/edtpass" android:layout_alignBottom="@+id/edtpass" android:layout_alignParentStart="true" android:text="@string/upass" /> <ProgressBar android:id="@+id/progress_login" style="@android:style/Widget.ProgressBar.Large" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:visibility="invisible" /></RelativeLayout>
结合实例再分析:
MVP之间的关系:M-数据和业务逻辑处理;V-界面显示:Activity;P-调用View接口 使用Model接口实现类与Model交互,Presenter内部含有View的接口实例和Model接口实现类的实例。
这是个人理解的MVP结构:
参考链接:
http://blog.csdn.net/jdsjlzx/article/details/51174396
http://blog.csdn.net/lmj623565791/article/details/46596109
如有错误或者其他意见,欢迎讨论和吐槽。
- 框架模式笔记:MVC 与MVP框架(完)
- Android框架模式之MVC与MVP
- 框架模式MVC与MVP的区别
- Android MVP与MVC框架模式
- MVC、MVP、MVVM框架模式
- 框架模式MVC与MVP在Android中的应用
- 框架模式MVC与MVP在Android中的应用
- 框架模式MVC与MVP在Android中的应用
- 框架模式MVC与MVP在Android中的应用
- 框架模式MVC与MVP在Android中的应用
- MVP 框架模式(学习笔记)
- iOS 框架模式(简述 MVC,MVP,MVVM 和 VIPER)
- IOS- 框架模式(简述 MVC,MVP,MVVM 和 VIPER)
- iOS 框架模式(简述 MVC,MVP,MVVM 和 VIPER)
- iOS 框架模式(简述 MVC,MVP,MVVM 和 VIPER)
- MVC、MVVM、MVP 框架设计模式浅析
- Android MVC、MVP、MVVM模式框架
- 浅谈mvc、mvp、mvvm框架模式
- 虚拟机参数总结
- css 竖直居中
- 【3.9】
- 20条LINUX常用命令
- poj3414
- 框架模式笔记:MVC 与MVP框架(完)
- CentOS下安装mysql
- 每日十道面试题(四)
- 51nod1202【DP-树状数组维护】
- 22.冒泡,选择,插入,希尔,快速,堆排序
- 剑指offer练习Python(二)
- 主机与客户机桥接时,主机SSH连不上客户机
- C语言关于数组的部分总结
- This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its de 错误解决办法