这篇文章主要是来展示实际开发之中自己写的Code。
Demo是用一个简单的登陆来演示的。效果图如下:
包结构:
MainActivity.Java
public class MainActivity extends AppCompatActivity { private EditText etUserName, etPwd; private ProgressDialog dialog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); etUserName = (EditText) findViewById(R.id.editText); etPwd = (EditText) findViewById(R.id.editText2); dialog = new ProgressDialog(this); } public void login(View v) { final String userName = etUserName.getText().toString().trim(); final String pwd = etPwd.getText().toString().trim(); boolean isLegal = checkIsLegal(userName, pwd);//检查输入的合法性 if (isLegal) { dialog.show(); new Thread(new Runnable() { @Override public void run() { SystemClock.sleep(3000); if ("Ivy".equals(userName) && "123".equals(pwd)) { runOnUiThread(new Runnable() { @Override public void run() { dialog.dismiss(); Toast.makeText(MainActivity.this, "登陆成功:" + userName, Toast.LENGTH_LONG).show(); } }); } else { runOnUiThread(new Runnable() { @Override public void run() { dialog.dismiss(); Toast.makeText(MainActivity.this, "用户名或密码失败", Toast.LENGTH_LONG).show(); } }); } } }).start(); } else { Toast.makeText(this, "用户名或密码不能为空", Toast.LENGTH_LONG).show(); } } private boolean checkIsLegal(String name, String pwd) { return !TextUtils.isEmpty(name) && !TextUtils.isEmpty(pwd);//简单的判断非空判断 } }MVC包结构:
MainActivity.Java
这里新增了User的业务Bean,是为了将MainActivity中用户信息进行封装,然后传递给M层即UserLoginNet这个类。
UserLoginNet.java
public class UserLoginNet { public boolean sendUserLogin(User user) { SystemClock.sleep(3000); if ("Ivy".equals(user.getUserName()) && "123".equals(user.getPwd())) { return true; } else { return false; } } }发现MVC的代码减少量还是很少,在MainActivity这个类中依然夹杂着业务层和界面层信息。
如果将MainActivity这个类的业务层抽取出来就是MVP模式了。
MVP包结构:
MainActivity.Java
Model层不用改变,新增了UserLoginPresenter。
public class UserLoginPresenter { private IUserLoginView view; public UserLoginPresenter(IUserLoginView view) { //作为View可以是MainActivity也可以是Fragment,所以为了通用性,这里的思路是:放置参数为通用(抽象类或接口,实际开发中接口更通用) this.view = view; } public boolean checkIsLegal(User user) { return !TextUtils.isEmpty(user.getUserName()) && !TextUtils.isEmpty(user.getPwd());//简单的判断非空判断 } public void login(final User user) { new Thread(new Runnable() { @Override public void run() { UserLoginNet net = new UserLoginNet(); boolean success = net.sendUserLogin(user); if (success) { view.success(); } else { view.failed(); } } }).start(); } }作为View可以是MainActivity也可以是Fragment,所以为了通用性,这里的思路是:放置参数为通用(抽象类或接口,实际开发中接口更通用)
接口:
public interface IUserLoginView { void success(); void failed(); }作为接口,一定要把注释写清楚
Model层代码不变,还是同样的网络请求
public class UserLoginNet { public boolean sendUserLogin(User user) { SystemClock.sleep(3000); if ("Ivy".equals(user.getUserName()) && "123".equals(user.getPwd())) { return true; } else { return false; } } }业务Bean的代码很简单:
public class User { private String userName; private String pwd; public User(String userName, String pwd) { this.userName = userName; this.pwd = pwd; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } }详细信息请关注官方开发者论坛,里面会随时更新:
在使用 DataBinding 的 Module 中,如下配置:
android { .... dataBinding { enabled = true } }Data Binding Layout Files
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="user" type="com.example.User"/> </data> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.firstName}"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.lastName}"/> </LinearLayout> </layout>Data Data
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity); User user = new User("Test", "User"); binding.setUser(user); }Observable Objects
private static class User extends BaseObservable { private String firstName; private String lastName; @Bindable public String getFirstName() { return this.firstName; } @Bindable public String getLastName() { return this.lastName; } public void setFirstName(String firstName) { this.firstName = firstName; notifyPropertyChanged(BR.firstName); } public void setLastName(String lastName) { this.lastName = lastName; notifyPropertyChanged(BR.lastName); } }ObservableFields
private static class User { public final ObservableField<String> firstName = new ObservableField<>(); public final ObservableField<String> lastName = new ObservableField<>(); public final ObservableInt age = new ObservableInt(); }MainActivity:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // setContentView(R.layout.activity_main); ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); user = new User(); user.userName.set("ivy123"); user.pwd.set("123"); binding.setUser(user); new Thread(new Runnable() { @Override public void run() { SystemClock.sleep(3000); user.userName.set("ivy"); } }).start(); }4个Demo下载地址:
LoginDemos