M:Model 数据层(网络,数据库,文件存储等等…)
V:View UI层 View、Activity、Fragment/以及他们的子类
P:Presenter 中介(作用:将M层与V层进行关联,交互的中介)
下面实现一个登陆功能
/**
* @作者: hyc
* @时间: 2019/12/2
* @说明:模拟网络请求
**/
public class HttpUtils {
HttpResultListener resultListener;
public HttpUtils(String userName, int password, HttpResultListener resultListener) {
this.resultListener = resultListener;
if (userName.equals("10000") && password == 123456) {
resultListener.onResult("用户:10000 登录成功!");
} else {
resultListener.onResult("用户:10000 登录失败");
}
}
public interface HttpResultListener {
void onResult(String result);
}
}
LoginModel
/**
* @作者: hyc
* @时间: 2019/12/2
* @说明:M层,网络请求
**/
public class LoginModel1 {
public void login(String userName, int password, final HttpUtils.HttpResultListener httpResultListener) {
HttpUtils httpUtils = new HttpUtils(userName, password, new HttpUtils.HttpResultListener() {
@Override
public void onResult(String result) {
httpResultListener.onResult(result);
}
});
}
}
LoginView
public interface LoginView1 {
void loginResult(String result);
}
LoginPresenter
/**
* @作者: hyc
* @时间: 2019/12/2
* @说明:与M、V交互的中介
**/
public class LoginPresenter1 {
LoginModel1 loginModel;
LoginView1 loginView;
public LoginPresenter(LoginView1 loginView) {
this.loginModel = new LoginModel();
this.loginView = loginView;
}
public void login(String userName, int password) {
loginModel.login(userName, password, new HttpUtils.HttpResultListener() {
@Override
public void onResult(String result) {
if (loginView != null) {
loginView.loginResult(result);
}
}
});
}
}
MainActivity
public class MainActivity extends AppCompatActivity implements LoginView1 {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_login).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LoginPresenter1 loginPresenter = new LoginPresenter1(MainActivity.this);
loginPresenter.login("10000",123456);
}
});
}
@Override
public void loginResult(String result) {
TextView textView = findViewById(R.id.tv_result);
textView.setText(result);
}
}
R.layout.activity_main
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="登录请求"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
android:textSize="15sp"
android:layout_marginTop="10dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_login"
/>
androidx.constraintlayout.widget.ConstraintLayout>
分析问题:当Activity关闭的时候,而数据请求依然在进行,需要解除UI层与数据层的关联
解决方案:方法绑定、解绑
attachView ->绑定 、detachView -> 解绑
把之前创建的LoginModel1、LoginPresenter1、LoginView1复制到另一个包下。
项目列表如下
修改LoginPresenter2
public class LoginPresenter2 {
LoginModel2 loginModel;
LoginView2 loginView;
public LoginPresenter2() {
this.loginModel = new LoginModel2();
}
//绑定
public void attachView(LoginView2 loginView) {
this.loginView = loginView;
}
//解绑
public void detachView() {
this.loginView = null;
}
public void login(String userName, int password) {
loginModel.login(userName, password, new HttpUtils.HttpResultListener() {
@Override
public void onResult(String result) {
if (loginView != null) {
loginView.loginResult(result);
}
}
});
}
}
MainActivity修改
public class MainActivity extends AppCompatActivity implements LoginView2 {
private LoginPresenter2 loginPresenter2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_login).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
loginPresenter2 = new LoginPresenter2();
loginPresenter2.attachView(MainActivity.this);
loginPresenter2.login("10000", 123456);
}
});
}
@Override
public void loginResult(String result) {
TextView textView = findViewById(R.id.tv_result);
textView.setText(result);
}
@Override
protected void onDestroy() {
super.onDestroy();
loginPresenter2.detachView();
}
}
运行项目,结果一样。
分析问题:
现在写一个功能,没啥问题,如果功能多了,绑定和解除绑定会很烦,为了统一管理绑定
解决方法:抽象类(把公共抽取出来) -> BasePresenter
重复上一步复制操作
项目列表如下
新建BasePresenter
public abstract class BasePresenter {
private LoginView3 loginView;
//绑定
public void attachView(LoginView3 loginView) {
this.loginView = loginView;
}
//解绑
public void detachView() {
this.loginView = null;
}
public LoginView3 getLoginView() {
return loginView;
}
}
修改LoginPresenter
public class LoginPresenter3 extends BasePresenter {
LoginModel3 loginModel;
public LoginPresenter3() {
this.loginModel = new LoginModel3();
}
public void login(String userName, int password) {
loginModel.login(userName, password, new HttpUtils.HttpResultListener() {
@Override
public void onResult(String result) {
if (getLoginView() != null) {
getLoginView().loginResult(result);
}
}
});
}
}
再修改MainActivity
public class MainActivity extends AppCompatActivity implements LoginView3 {
private LoginPresenter3 loginPresenter3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_login).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
loginPresenter3 = new LoginPresenter3();
loginPresenter3.attachView(MainActivity.this);
loginPresenter3.login("10000", 123456);
}
});
}
@Override
public void loginResult(String result) {
TextView textView = findViewById(R.id.tv_result);
textView.setText(result);
}
@Override
protected void onDestroy() {
super.onDestroy();
loginPresenter3.detachView();
}
}
运行项目,结果一样
分析问题:BasePresenter抽象类写死了,只有LoginView,可能还会有登录或者注册,或者获取验证码,
希望能动态抽象
解决方案:BaseView解决
重复复制操作
项目列表如下
新建BaseView
public interface BaseView {
}
修改BasePresenter
public abstract class BasePresenter4 {
private BaseView loginView;
//绑定
public void attachView(BaseView loginView) {
this.loginView = loginView;
}
//解绑
public void detachView() {
this.loginView = null;
}
public BaseView getLoginView() {
return loginView;
}
}
修改LoginView4
public interface LoginView4 extends BaseView {
void loginResult(String result);
}
修改LoginPresenter4
public class LoginPresenter4 extends BasePresenter4 {
LoginModel4 loginModel;
public LoginPresenter4() {
this.loginModel = new LoginModel4();
}
public void login(String userName, int password) {
loginModel.login(userName, password, new HttpUtils.HttpResultListener() {
@Override
public void onResult(String result) {
if (getLoginView() != null) {
//这里强转
LoginView4 view= (LoginView4) getLoginView();
view.loginResult(result);
}
}
});
}
}
修改MainActivity
public class MainActivity extends AppCompatActivity implements LoginView4 {
private LoginPresenter4 loginPresenter4;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_login).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
loginPresenter4 = new LoginPresenter4();
loginPresenter4.attachView(MainActivity.this);
loginPresenter4.login("10000", 123456);
}
});
}
@Override
public void loginResult(String result) {
TextView textView = findViewById(R.id.tv_result);
textView.setText(result);
}
@Override
protected void onDestroy() {
super.onDestroy();
loginPresenter4.detachView();
}
}
运行项目,结果一样
分析问题:每次都需要强制类型转换。
解决方案:泛型设计
重复复制操作
项目列表如下
修改BasePresenter5
public abstract class BasePresenter5 <V extends BaseView5>{
private V loginView;
//绑定
public void attachView(V loginView) {
this.loginView = loginView;
}
//解绑
public void detachView() {
this.loginView = null;
}
public V getLoginView() {
return loginView;
}
}
修改LoginPresenter5
public class LoginPresenter5 extends BasePresenter5<LoginView5> {
LoginModel5 loginModel;
public LoginPresenter5() {
this.loginModel = new LoginModel5();
}
public void login(String userName, int password) {
loginModel.login(userName, password, new HttpUtils.HttpResultListener() {
@Override
public void onResult(String result) {
if (getLoginView() != null) {
getLoginView().loginResult(result);
}
}
});
}
}
修改MainActivity
public class MainActivity extends AppCompatActivity implements LoginView5 {
private LoginPresenter5 loginPresenter5;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_login).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
loginPresenter5 = new LoginPresenter5();
loginPresenter5.attachView(MainActivity.this);
loginPresenter5.login("10000", 123456);
}
});
}
@Override
public void loginResult(String result) {
TextView textView = findViewById(R.id.tv_result);
textView.setText(result);
}
@Override
protected void onDestroy() {
super.onDestroy();
loginPresenter5.detachView();
}
}
运行项目,结果一样
分析问题:一个Activity需要去绑定与解除绑定,如果Activty和Fragment多了,很多代码冗余
解决方案:抽象类 ->抽象出绑定与解除绑定 ->BaseActivity
重复复制操作
项目列表如下
新建BaseActivity
public abstract class BaseActivity extends AppCompatActivity {
private LoginPresenter6 presenter6;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
}
private void init() {
presenter6 = createPresenter();
presenter6.attachView(createView());
}
public LoginPresenter6 getPresenter6() {
return presenter6;
}
public abstract LoginPresenter6 createPresenter();
public abstract LoginView6 createView();
@Override
protected void onDestroy() {
super.onDestroy();
presenter6.detachView();
}
}
修改MainActivity
public class MainActivity extends BaseActivity implements LoginView6 {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_login).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getPresenter6().login("10000", 123456);
}
});
}
@Override
public LoginPresenter6 createPresenter() {
return new LoginPresenter6();
}
@Override
public LoginView6 createView() {
return this;
}
@Override
public void loginResult(String result) {
TextView textView = findViewById(R.id.tv_result);
textView.setText(result);
}
}
运行项目,结果一样
分析问题:BaseActivity还是写死了,未满足要求,只能用LoginPresenter6
解决方案:BaseActivity中抽象实现(BasePresenter和BaseView)
重复复制操作
项目列表如下
修改BaseActivity7
public abstract class BaseActivity7 extends AppCompatActivity {
private BasePresenter7 presenter7;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
}
private void init() {
presenter7 = createPresenter();
presenter7.attachView(createView());
}
public BasePresenter7 getPresenter7() {
return presenter7;
}
public abstract BasePresenter7 createPresenter();
public abstract BaseView7 createView();
@Override
protected void onDestroy() {
super.onDestroy();
presenter7.detachView();
}
}
修改MainActivity
public class MainActivity extends BaseActivity7 implements LoginView7 {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_login).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LoginPresenter7 presenter7 = (LoginPresenter7) getPresenter7();
presenter7.login("10000", 123456);
}
});
}
@Override
public LoginPresenter7 createPresenter() {
return new LoginPresenter7();
}
@Override
public LoginView7 createView() {
return this;
}
@Override
public void loginResult(String result) {
TextView textView = findViewById(R.id.tv_result);
textView.setText(result);
}
}
运行项目,结果一样
分析问题:还需要强制类型转换
解决方案:泛型设计
重复复制操作
项目列表如下
修改BaseActivity8
public abstract class BaseActivity8<V extends BaseView8, P extends BasePresenter8<V>> extends AppCompatActivity {
private P presenter8;
private V view8;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
}
private void init() {
presenter8 = createPresenter();
if (presenter8 == null) {
throw new NullPointerException("presenter8 is null");
}
view8 = createView();
if (view8 == null) {
throw new NullPointerException("view8 is null");
}
presenter8.attachView(view8);
}
public P getPresenter8() {
return presenter8;
}
public abstract P createPresenter();
public abstract V createView();
@Override
protected void onDestroy() {
super.onDestroy();
if (presenter8 != null) {
presenter8.detachView();
}
}
}
修改MainActivity
public class MainActivity extends BaseActivity8<LoginView8, LoginPresenter8> implements LoginView8 {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_login).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getPresenter8().login("10000", 123456);
}
});
}
@Override
public LoginPresenter8 createPresenter() {
return new LoginPresenter8();
}
@Override
public LoginView8 createView() {
return this;
}
@Override
public void loginResult(String result) {
TextView textView = findViewById(R.id.tv_result);
textView.setText(result);
}
}
运行项目,结果一样
我也是学习别人的自己总结记录下来,方便以后查看,俗话说,好记性不如烂笔头,文章写得不是很好,不喜勿喷,谢谢,有错误的地方,欢迎留言
源码入口github如果有帮助请帮我start 感谢!。