一  MVC模式:

M:model,业务逻辑

V:view,对应布局文件

C:Controllor,对应Activity

项目框架:

代码部分:

  layout文件(适用于MVC和MVP两个Demo):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><EditTextandroid:id="@+id/edit_username"android:layout_width="match_parent"android:layout_height="50dp"android:hint="username"/><EditTextandroid:id="@+id/edit_password"android:layout_width="match_parent"android:layout_height="50dp"android:inputType="textPassword"android:hint="password"/><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><Buttonandroid:id="@+id/login"android:layout_marginLeft="10dp"android:layout_width="120dp"android:layout_height="50dp"android:text="Login"/><Buttonandroid:id="@+id/clear"android:layout_width="120dp"android:layout_height="50dp"android:layout_marginLeft="100dp"android:text="Clear"/></LinearLayout><ProgressBarandroid:id="@+id/login_progressbar"android:layout_width="match_parent"android:layout_height="wrap_content"android:visibility="invisible"/>
</LinearLayout>

  User类,定义成员对象:

package com.example.liang.userloginformvc.modle;/*** Created by liang on 2016/8/22.*/
public class User {private String username;private String password;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}
}

  OnLoginListener,j监听登陆状态:

package com.example.liang.userloginformvc.modle;/*** Created by liang on 2016/8/22.*/
public interface OnLoginListener {void loginSuccess(User user);void loginFailed();
}

  UserBiz,登陆逻辑:

package com.example.liang.userloginformvc.modle;/*** Created by liang on 2016/8/22.*/
public class UserBiz {public void login(final String username,final String password,final OnLoginListener loginListener){new Thread(){@Overridepublic void run() {try{Thread.sleep(2000);}catch(InterruptedException e){e.printStackTrace();}//模拟登陆if("lqy".equals(username)&&"123".equals(password)){User user=new User();user.setUsername(username);user.setPassword(password);loginListener.loginSuccess(user);}else{loginListener.loginFailed();}}}.start();}
}

MVC模式总结:

  首先从响应用户点击事件,到MainActivity,获取View中的数据再交给Model层处理,通过返回的数据,MainActivity再改变视图。

从MVC到MVP:由于View和Model之间的依赖还是太强,希望他们可以绝对独立的存在,慢慢的就演化出了MVP

二  MVP模式

M:业务逻辑与实体模型

V:负责View的绘制以及用户交互,对应Activity

P:负责完成View与Modle之间的交换

项目框架:

代码部分:

  user:

package com.example.liang.userloginformvp.bean;/*** Created by liang on 2016/8/22.*/
public class User{private String username;private String password;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}
}

  IUserBiz:

package com.example.liang.userloginformvp.biz;/*** Created by liang on 2016/8/22.*/
public interface IUserBiz{public void login(String username,String password,OnLoginListener onLoginListener);
}

  OnLoginListener:

package com.example.liang.userloginformvp.biz;/*** Created by liang on 2016/8/22.*/
public interface IUserBiz{public void login(String username,String password,OnLoginListener onLoginListener);
}

  UserBiz:

package com.example.liang.userloginformvp.biz;import com.example.liang.userloginformvp.bean.User;/*** Created by liang on 2016/8/22.*/
public class UserBiz implements IUserBiz {//在这里重写IUserBiz中的方法
    @Overridepublic void login(final String username, final String password, final OnLoginListener loginListener) {//注意,这里并没有new OnLoginListener的对象,所以也没有重写方法//要留在UserLoginPresenter中重写,并通过登陆的状态调用相应的视图new Thread(){@Overridepublic void run() {try{Thread.sleep(2000);}catch(InterruptedException e){e.printStackTrace();}//模拟登陆成功if("lqy".equals(username)&&"123".equals(password)){User user=new User();user.setUsername(username);user.setPassword(password);loginListener.loginSuccess(user);}else{loginListener.loginFailed();}}}.start();}
}

  UserLoginPresenter:

public class UserLoginPresenter {private IUserBiz userBiz;private IUserLoginView userLoginView;private Handler mHandler = new Handler();public UserLoginPresenter(IUserLoginView userLoginView) {this.userLoginView = userLoginView;//给userBiz一个子类的空间,此时方法已经被重写,登陆逻辑已被判断this.userBiz = new UserBiz();}public void login() {userLoginView.showLoading();userBiz.login(userLoginView.getUserName(), userLoginView.getPassword(), new OnLoginListener() {@Overridepublic void loginSuccess(final User user) {//需要在UI线程执行mHandler.post(new Runnable() {@Overridepublic void run() {userLoginView.toMainActivity(user);userLoginView.hideLoading();}});}@Overridepublic void loginFailed() {//需要在UI线程执行mHandler.post(new Runnable() {@Overridepublic void run() {userLoginView.showFailedError();userLoginView.hideLoading();}});}});}public void clear() {userLoginView.clearUserName();userLoginView.clearPassword();}}

  IUserLoginPresenter:

package com.example.liang.userloginformvp.view;import com.example.liang.userloginformvp.bean.User;/*** Created by liang on 2016/8/22.*/
public interface IUserLoginView {String getUserName();String getPassword();void clearUserName();void clearPassword();void showLoading();void hideLoading();void toMainActivity(User user);void showFailedError();
}

  MainActivity:

package com.example.liang.userloginformvp;import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;import com.example.liang.userloginformvp.bean.User;
import com.example.liang.userloginformvp.presenter.UserLoginPresenter;
import com.example.liang.userloginformvp.view.IUserLoginView;public class MainActivity extends ActionBarActivity implements IUserLoginView{private EditText usernaem_edit,password_edit;private Button login_btn,clear_btn;private ProgressBar loading;private UserLoginPresenter userLoginPresenter=new UserLoginPresenter(this);@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initViews();}private void initViews(){usernaem_edit=(EditText)findViewById(R.id.edit_username);password_edit=(EditText)findViewById(R.id.edit_password);login_btn=(Button)findViewById(R.id.login);clear_btn=(Button)findViewById(R.id.clear);loading=(ProgressBar)findViewById(R.id.login_progressbar);loading.setVisibility(View.INVISIBLE);login_btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {userLoginPresenter.login();}});clear_btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {userLoginPresenter.clear();}});}@Overridepublic String getUserName() {return usernaem_edit.getText().toString();}@Overridepublic String getPassword() {return password_edit.getText().toString();}@Overridepublic void clearUserName() {usernaem_edit.setText("");}@Overridepublic void clearPassword() {password_edit.setText("");}@Overridepublic void showLoading() {loading.setVisibility(View.VISIBLE);}@Overridepublic void hideLoading() {loading.setVisibility(View.GONE);}@Overridepublic void toMainActivity(User user) {Toast.makeText(this,user.getUsername()+" login success , to MainActivity",Toast.LENGTH_SHORT).show();}@Overridepublic void showFailedError() {Toast.makeText(this, "login failed", Toast.LENGTH_SHORT).show();}
}

MVP总结:Activity作为View加载视图并响应点击事件(直接想登陆),点击事件交由Presenter处理,Presenter将登陆逻辑交给Model处理,并根据model处理结果告诉View改返回什么试图。

------------------------------------分隔线

从MVP到MVVM中:至于MVVM基本上和MVP一模一样,感觉只是名字替换了一下。他的关键技术就是今天的主题(Data Binding)。View的变化可以自动的反应在ViewModel,ViewModel的数据变化也会自动反应到View上。这样开发者就不用处理接收事件和View更新的工作,框架已经帮你做好了。

三  MVVM模式

M:model,业务逻辑

V:加载视图,和layout通信,进行数据绑定与更新,对应Activity(由于代码是在太少,有时自带启动自己的方法)

VM:判断条件,逻辑实现

项目框架:

首先配置环境

加一句:

  LoginViewModel

package com.example.liang.userloginformvvm.viewmodel;import android.content.Context;
import android.databinding.ObservableField;
import android.databinding.ObservableInt;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;import com.example.liang.userloginformvvm.modle.User;
import com.example.liang.userloginformvvm.view_activity.MainActivity;/*** Created by liang on 2016/8/23.*/
public class LoginViewModel implements ViewModel {private Context context;//用于数据刷新的便捷类型:ObservableField,ObservableInt····public ObservableField<String> loginMessage;public ObservableInt loginMessageVisibility;private String editTextUsernameValue = "";private String editTextPasswordValue = "";public LoginViewModel(Context context) {this.context = context;this.loginMessage = new ObservableField<>("");this.loginMessageVisibility = new ObservableInt(View.INVISIBLE);}//登陆,实际上这个方法是在layout文件中调用的public void loginAuthentication(View view) {if ((editTextUsernameValue.equals("lqy")) && (editTextPasswordValue.equals("123"))) {loginMessage.set("");loginMessageVisibility.set(View.INVISIBLE);User user = new User(editTextUsernameValue, editTextPasswordValue);context.startActivity(MainActivity.newIntent(context, user));} else if ((editTextUsernameValue.equals("")) || (editTextPasswordValue.equals(""))) {loginMessage.set("Username or Password can't be empty!");loginMessageVisibility.set(View.VISIBLE);} else {loginMessage.set("Username = lqy \n Password = 123");loginMessageVisibility.set(View.VISIBLE);}}//观察Text变化的TextWatcherpublic TextWatcher getUsernameUpdate() {return new TextWatcher() {@Overridepublic void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}@Overridepublic void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {editTextUsernameValue = charSequence.toString();}@Overridepublic void afterTextChanged(Editable editable) {}};}public TextWatcher getPasswordUpdate() {return new TextWatcher() {@Overridepublic void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}@Overridepublic void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {editTextPasswordValue = charSequence.toString();}@Overridepublic void afterTextChanged(Editable editable) {}};}@Overridepublic void destroy() {}
}

  MainViewModel:

package com.example.liang.userloginformvvm.viewmodel;import android.content.Context;import com.example.liang.userloginformvvm.modle.User;/*** Created by liang on 2016/8/23.*/
public class MainViewModel {private Context context;private User user;public MainViewModel(Context context, User user) {this.context = context;this.user = user;}public String getUsername(){return user.username;}public String getPassword(){return user.password;}
}

  ViewModel:

package com.example.liang.userloginformvvm.viewmodel;/*** Created by liang on 2016/8/23.*/
public interface ViewModel {void destroy();
}

  User:

package com.example.liang.userloginformvvm.modle;import android.os.Parcel;
import android.os.Parcelable;/*** Created by liang on 2016/8/23.*/
//实现Parcelable接口,可以让类在网络或进程中传递
public class User implements Parcelable{public String username;public String password;public User(String username,String password){this.username=username;this.password=password;}public User(Parcel in) {username = in.readString();password = in.readString();}public static final Creator<User> CREATOR=new Creator<User>() {@Overridepublic User createFromParcel(Parcel parcel) {return new User(parcel);}@Overridepublic User[] newArray(int i) {return new User[i];}};@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel parcel, int i) {parcel.writeString(this.username);parcel.writeString(this.password);}
}

  

  LoginActivity

package com.example.liang.userloginformvvm.view_activity;import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;import com.example.liang.userloginformvvm.R;
import com.example.liang.userloginformvvm.databinding.ActivityLoginBinding;
import com.example.liang.userloginformvvm.viewmodel.LoginViewModel;/*** Created by liang on 2016/8/23.*/
public class LoginActivity extends AppCompatActivity{//当给布局指定格式之后会产生相应的Bing类,例如activity_login.xml会产生ActivityLoginBinding类
    ActivityLoginBinding loginBinding;LoginViewModel viewModel;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//指定布局,没有XXX.findViewById了loginBinding = DataBindingUtil.setContentView(this, R.layout.activity_login);viewModel=new LoginViewModel(this);loginBinding.setViewmodel(viewModel);}
}

  MainActivity

package com.example.liang.userloginformvvm.view_activity;import android.content.Context;
import android.content.Intent;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;import com.example.liang.userloginformvvm.R;
import com.example.liang.userloginformvvm.databinding.ActivityMainBinding;
import com.example.liang.userloginformvvm.modle.User;
import com.example.liang.userloginformvvm.viewmodel.MainViewModel;/*** Created by liang on 2016/8/23.*/
public class MainActivity extends AppCompatActivity{ActivityMainBinding activityMainBinding;MainViewModel mainViewModel;//传递数据的标志private static final String EXTRA_USER = "extra_user";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);activityMainBinding= DataBindingUtil.setContentView(this, R.layout.activity_main);User user=getIntent().getParcelableExtra(EXTRA_USER);mainViewModel=new MainViewModel(this,user);activityMainBinding.setMainviewmodel(mainViewModel);}//viewmodel唤醒这个Activity的方法public static Intent newIntent(Context context, User user){Intent intent = new Intent(context, MainActivity.class);intent.putExtra(EXTRA_USER,user);return intent;}
}

  下面就是非常重要的layout文件了:

activity_mian.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"><data><variablename="viewmodel"type="com.example.liang.userloginformvvm.viewmodel.LoginViewModel"></variable></data><!--先要指定绑定的类--><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"tools:context=".view_activity.LoginActivity"><TextViewandroid:id="@+id/loginmessage"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{viewmodel.loginMessage}"android:textAlignment="center"android:textColor="@color/colorAccent"android:layout_centerHorizontal="true"android:layout_marginTop="20dp"android:layout_marginBottom="20dp"/><!--监听text的变化--><EditTextandroid:id="@+id/login_username"android:layout_width="wrap_content"android:layout_height="wrap_content"android:inputType="textPersonName"android:ems="10"android:layout_centerHorizontal="true"android:layout_below="@+id/loginmessage"android:hint="UserName"android:layout_marginBottom="10dp"app:addTextChangedListener="@{viewmodel.usernameUpdate}"/><EditTextandroid:id="@+id/login_password"android:layout_width="wrap_content"android:layout_height="wrap_content"android:inputType="textPassword"android:hint="Password"android:ems="10"android:layout_below="@id/login_username"android:layout_centerHorizontal="true"android:layout_marginBottom="10dp"app:addTextChangedListener="@{viewmodel.passwordUpdate}" /><Buttonandroid:layout_width="210dp"android:layout_height="wrap_content"android:text="LOGIN"android:layout_below="@id/login_password"android:layout_centerHorizontal="true"android:onClick="@{viewmodel.loginAuthentication}"/></RelativeLayout>
</layout>

activity_login.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"><data><variablename="mainviewmodel"type="com.example.liang.userloginformvvm.viewmodel.MainViewModel"></variable></data><LinearLayoutandroid:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".view_activity.MainActivity"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="60dp"android:orientation="horizontal"><TextViewandroid:layout_width="0dp"android:layout_height="match_parent"android:text="Welcome"android:layout_weight="1"/><TextViewandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="3"android:text="@{mainviewmodel.username}"/></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="60dp"android:orientation="horizontal"><TextViewandroid:layout_width="0dp"android:layout_height="match_parent"android:text="Password is"android:layout_weight="1"/><TextViewandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="3"android:text="@{mainviewmodel.password}"/></LinearLayout></LinearLayout></layout>

MVVM总结:通过View加载布局,并通过布局调用ViewModel中的方法,VeiwModel可以通过调用后的结果决定启动什么视图,同时ViewModel保持和model的通信。

2016.8.24首次截稿

有什么错误麻烦大家指出来,在线更新。

参考资料:

鸿洋老师的博客: http://blog.csdn.net/lmj623565791/article/details/46596109

胡笛老师的微信推文

还有github上的资源

以及http://my.oschina.net/u/1175007/blog/613889

转载于:https://www.cnblogs.com/Liang-Blog/p/5801414.html

Android MVC,MVP,MVVM模式入门——重构登陆注册功能相关推荐

  1. Android中常见的MVC/MVP/MVVM模式

    Android中常见的MVC/MVP/MVVM模式 经典MVC 在1979年,经典MVC模式被提出. 在当时,人们一直试图将纯粹描述思维中的对象与跟计算机环境打交道的代码隔离开来,而Trygve Re ...

  2. Android的MVC MVP MVVM模式

    学习Android的同学一定要了解的三种开发模式,不然自己写的项目采用的什么模式都不清楚 MVC,MVP,MVVM都是为了解决UI页面与逻辑代码分离而出现的模式,MVP和MVVM都是MVC的基础上演化 ...

  3. android MVC,MVP,MVVM

    1.MVC思想 无论在任何情况下,软件设计都要符合高内聚,低耦合的思想.如果背离这一原则,代码将很难进入维护. MVC出现与上世纪70年代,在三十多年的工程实践中,MVC充分证明了它的成功.在软件开发 ...

  4. android MVC,MVP,MVVM概论

    1.MVC思想 无论在任何情况下,软件设计都要符合高内聚,低耦合的思想.如果背离这一原则,代码将很难进入维护. MVC出现与上世纪70年代,在三十多年的工程实践中,MVC充分证明了它的成功.在软件开发 ...

  5. Android MVC ,MVP,MVVM 常见架构浅谈

    简述:其实任何架构的目的都是:提高开发效率,降低维护成本: MVC: Model: 负责处理数据逻辑,一般包括操作数据库,耗时网络操作等组成: View:负责处理视图: 一般是xml布局: Contr ...

  6. Android架构设计之MVC/MVP/MVVM浅析

    目录 写在前面 一.案例演示 二.MVC模式 2.1.MVC简介 2.2.MVC模式的使用 2.3.MVC模式的缺点 三.MVP模式 3.1.MVP简介 3.2.MVP模式的作用 3.3.MVP模式的 ...

  7. Android 实现简单的登陆注册功能(SharedPreferences和SQLite)

    最近刚好做了一个Android的登录注册界面,将数据利用SharedPreferences或者SQLite绑定到Android程序中,实现简单的登陆注册功能,本文未涉及到与服务器的交流. 首先,对于登 ...

  8. Android App的设计架构:MVC,MVP,MVVM与架构经验谈

    本文转载自https://www.tianmaying.com/tutorial/AndroidMVC,原文作者周鸿博. 和MVC框架模式一样,Model模型处理数据代码不变在Android的App开 ...

  9. Android 系统(77)---MVC,MVP,MVVM的区别

    MVC,MVP,MVVM的区别 一.MVC 软件可以分为三部分 1.Model:模型层,负责处理数据的加载或者存储  2. View:视图层,负责界面数据的展示,与用户进行交互  3.Controll ...

最新文章

  1. 由于市场判断失误 希捷降低收入预期
  2. python100行代码-python代码行数统计 100行
  3. macos怎么pdf转换成word,妈妈再也不用担心我的mac了
  4. 第七章之main函数和启动例程
  5. VTK:图片之Gradient
  6. [Google Guava] 2.3-强大的集合工具类:java.util.Collections中未包含的集合工具
  7. SAP CRM和C4C message category配置
  8. .NET 5 尝鲜 - 开源项目TerminalMACS WPF管理端支持.NET 5
  9. 数据挖掘的相关知识例子
  10. Rtworld目录网全解开源2.0-功能齐全
  11. 系统监控之SNMP协议理解
  12. 建立一个普通方法无法打开查看和删除的文件夹
  13. 【BZOJ 2301】[HAOI2011]Problem b
  14. 账号集中管理系统设计与实现----OpenLDAP
  15. 为Android系统定制重启功能
  16. 最大熵图像复原方法原理(附完整代码)
  17. nginx 做代理转发 对文件上传下载有影响速度吗_少年: Nginx了解下
  18. 小米路由器3 SCUT校园网刷scut-padavan固件方法
  19. 请选择正确html,请选择可以使单元格中的内容进行左对齐的正确HTML标记(      )。...
  20. JavaScript高级之42个英语单词

热门文章

  1. Huawei FusionCompute安装体验
  2. 获取文件绝对路径和目录
  3. HDOJ 1905 Pseudoprime numbers(模运算)
  4. windows2003 mstsc 远端连线,减少可会话数目 ,同一用户只允许一个会话
  5. CCNA培训课总结笔记--配置OSPF实验(十一)
  6. java class对象创建时机_Java面向对象编程-类的声明周期
  7. python print怎么用_python print用法是什么
  8. 关于xilinx fir use reloadable coefficient的用法
  9. MinGW-w64安装教程——著名C/C++编译器GCC的Windows版本
  10. vue实现点击后多级标题联动变化