高效的使用MVP
来源:互联网 发布:为什么安装不了知乎 编辑:程序博客网 时间:2024/05/16 03:20
(1)说明
写mvp的时候,presenter会持有view,如果presenter有后台异步的长时间的动作,比如网络请求,这时如果返回退出了Activity,后台异步的动作不会立即停止,这里就会有内存泄漏的隐患,所以会在presenter中加入一个销毁view的方法。但是当后台的延时操作返回时,这个时候view被销毁了,如果接着去调用view的方法就 会抛出空指针异常。所以在后台的延时操作中需要考虑到这种可能产生空指针的情况,尤其是网络请求。
(2)创建基类和使用
① Presenter
如果每一个Activity都需要做绑定和解绑操作就太麻烦,现在可以用一个通用的presenter来为我们添加view的绑定与销毁。
public abstract class BasePresenter<T> {
public T mView;
public void attach(T mView) {
this.mView = mView;
}
public void dettach() {
mView = null;
}
}
因为不能限定死传入的View,所以使用泛型来代替传入的对象。通过这个通用的presenter可以把原来的LoginPresenter简化成下面的样子。
public class LoginPresenter extends BasePresenter<LoginView>{
private final LoginData loginData;
private Handler mHandler;
public LoginPresenter() {
loginData = new LoginData();
mHandler = new Handler();
}
public void login() {
//点击登录时
if (TextUtils.isEmpty(mView.getUserName())){
mView.showFailedError("请输入用户名");
}else if (TextUtils.isEmpty(mView.getPassword())){
mView.showFailedError("请输入密码");
}else {
mView.showLoading();
loginData.login(mView.getUserName(), mView.getPassword(), new GetNetListener() {
@Override
public void loginSuccess(Stringrequest) {
//需要在UI线程执行
mHandler.post(new Runnable() {
@Override
public void run() {
mView.hideLoading();
mView.toMainActivity();
}
});
}
@Override
public void loginFailed(final String err) {
mHandler.post(new Runnable() {
@Override
public void run() {
mView.hideLoading();
mView.showFailedError(err);
}
});
}
});
}
}
public void toPassWroad() {
//修改密码界面
mView.toPassWroad();
}
② View
界面需要提供的UI方法中会有很多类似的UI方法,可以把它们提取到一个公共的父类接口中。比如提取显示loading界面和隐藏loading界面的方法,其他的view层接口就可以直接继承BaseView接口,不必重复的写显示和隐藏loading界面方法。
public interface BaseView {
void showLoading();
void hideLoading();
}
具体实现类
public interface LoginView extends BaseView {
String getUserName();
String getPassword();
void clearUserName();
void clearPassword();
void toMainActivity();
void showFailedError(String message);
void toPassWroad();
}
presenter绑定到activity和View的绑定和解绑操作是每个Activity都会去做的,同样这里我也希望能有一个父类来完成这个统一的操作。
public class LoginActivity extends BaseActivity<LoginView,LoginPresenter> implements LoginView {
private EditText etUsername;
private EditText etPassword;
private LinearLayout llForgetpass;
private Button btLogin;
private LinearLayout llLoginQuan;
@Override
public void initView() {
setContentView(R.layout.activity_login);
etUsername = (EditText)findViewById(R.id.et_username);
etPassword = (EditText)findViewById(R.id.et_password);
llForgetpass = (LinearLayout)findViewById(R.id.ll_forgetpass);
btLogin = (Button)findViewById(R.id.bt_login);
llLoginQuan = (LinearLayout)findViewById(R.id.ll_login_quan);
}
@Override
public void initData() {
btLogin.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
presenter.login();
}
});
llForgetpass.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
presenter.toPassWroad();
}
});
}
@Override
public LoginPresenterinitPresenter() {
return new LoginPresenter();
}
@Override
public StringgetUserName() {
return etUsername.getText().toString().trim();
}
@Override
public String getPassword(){
return etPassword.getText().toString().trim();
}
@Override
public void clearUserName() {
etUsername.setText("");
}
@Override
public void clearPassword() {
etPassword.setText("");
}
@Override
public void toMainActivity() {
startActivity(new Intent(this, MainActivity.class));
}
@Override
public void showFailedError(Stringmessage) {
Toast.makeText(LoginActivity.this, message, Toast.LENGTH_SHORT).show();
}
@Override
public void toPassWroad() {
startActivity(new Intent(LoginActivity.this,ForgetPassActivity.class));
}
@Override
public void showLoading() {
llLoginQuan.setVisibility(View.VISIBLE);
}
@Override
public void hideLoading() {
llLoginQuan.setVisibility(View.GONE);
}
}
③model
监听网络请求
public interface GetNetListener {
//请求成功的监听
void loginSuccess(Stringrequest);
//请求失败的监听
void loginFailed(Stringerr);
}
/**
* Created by ylzx on 2016/12/21.
* 请求网络的方法
*/
public abstract class GetNet {
//登录接口
public void login(Stringusername, String password, GetNetListener loginListener){};
}
/**
* Created by ylzx on 2016/12/21.
* 请求网络
*/
public class LoginData extends GetNet {
public String TAG="LoginData";
private GetNetListener mLoginListener;
@Override
public void login(Stringusername, String password, GetNetListener loginListener) {
this.mLoginListener = loginListener;
//网络请求
try {
HashMap<String, String>sortedParams = new HashMap<String, String>();
sortedParams.put("accountID", username);
OkHttpUtils
.post()
.url(url)
.params(params)
.build()
.execute(new MyStringCallback());
} catch (Exception e) {
e.printStackTrace();
}
}
class MyStringCallback extends StringCallback {
@Override
public void onError(Call call,Exception e, int id) {
mLoginListener.loginFailed(e.toString());
}
@Override
public void onResponse(Stringresponse, int id) {
BaseModel baseModel =GsonUtil.jsonToBean(response, BaseModel.class);
if (baseModel.isFlag()){
//成功
mLoginListener.loginSuccess(response);
} else {
//错误时
mLoginListener.loginFailed(baseModel.getErrorMsg());
}
}
}
}
4.高效的使用MVP
(1)说明
写mvp的时候,presenter会持有view,如果presenter有后台异步的长时间的动作,比如网络请求,这时如果返回退出了Activity,后台异步的动作不会立即停止,这里就会有内存泄漏的隐患,所以会在presenter中加入一个销毁view的方法。但是当后台的延时操作返回时,这个时候view被销毁了,如果接着去调用view的方法就 会抛出空指针异常。所以在后台的延时操作中需要考虑到这种可能产生空指针的情况,尤其是网络请求。
(2)创建基类和使用
① Presenter
如果每一个Activity都需要做绑定和解绑操作就太麻烦,现在可以用一个通用的presenter来为我们添加view的绑定与销毁。
public abstract class BasePresenter<T> {
public T mView;
public void attach(T mView) {
this.mView = mView;
}
public void dettach() {
mView = null;
}
}
因为不能限定死传入的View,所以使用泛型来代替传入的对象。通过这个通用的presenter可以把原来的LoginPresenter简化成下面的样子。
public class LoginPresenter extends BasePresenter<LoginView>{
private final LoginData loginData;
private Handler mHandler;
public LoginPresenter() {
loginData = new LoginData();
mHandler = new Handler();
}
public void login() {
//点击登录时
if (TextUtils.isEmpty(mView.getUserName())){
mView.showFailedError("请输入用户名");
}else if (TextUtils.isEmpty(mView.getPassword())){
mView.showFailedError("请输入密码");
}else {
mView.showLoading();
loginData.login(mView.getUserName(), mView.getPassword(), new GetNetListener() {
@Override
public void loginSuccess(Stringrequest) {
//需要在UI线程执行
mHandler.post(new Runnable() {
@Override
public void run() {
mView.hideLoading();
mView.toMainActivity();
}
});
}
@Override
public void loginFailed(final String err) {
mHandler.post(new Runnable() {
@Override
public void run() {
mView.hideLoading();
mView.showFailedError(err);
}
});
}
});
}
}
public void toPassWroad() {
//修改密码界面
mView.toPassWroad();
}
② View
界面需要提供的UI方法中会有很多类似的UI方法,可以把它们提取到一个公共的父类接口中。比如提取显示loading界面和隐藏loading界面的方法,其他的view层接口就可以直接继承BaseView接口,不必重复的写显示和隐藏loading界面方法。
public interface BaseView {
void showLoading();
void hideLoading();
}
具体实现类
public interface LoginView extends BaseView {
String getUserName();
String getPassword();
void clearUserName();
void clearPassword();
void toMainActivity();
void showFailedError(String message);
void toPassWroad();
}
presenter绑定到activity和View的绑定和解绑操作是每个Activity都会去做的,同样这里我也希望能有一个父类来完成这个统一的操作。
public class LoginActivity extends BaseActivity<LoginView,LoginPresenter> implements LoginView {
private EditText etUsername;
private EditText etPassword;
private LinearLayout llForgetpass;
private Button btLogin;
private LinearLayout llLoginQuan;
@Override
public void initView() {
setContentView(R.layout.activity_login);
etUsername = (EditText)findViewById(R.id.et_username);
etPassword = (EditText)findViewById(R.id.et_password);
llForgetpass = (LinearLayout)findViewById(R.id.ll_forgetpass);
btLogin = (Button)findViewById(R.id.bt_login);
llLoginQuan = (LinearLayout)findViewById(R.id.ll_login_quan);
}
@Override
public void initData() {
btLogin.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
presenter.login();
}
});
llForgetpass.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
presenter.toPassWroad();
}
});
}
@Override
public LoginPresenterinitPresenter() {
return new LoginPresenter();
}
@Override
public StringgetUserName() {
return etUsername.getText().toString().trim();
}
@Override
public String getPassword(){
return etPassword.getText().toString().trim();
}
@Override
public void clearUserName() {
etUsername.setText("");
}
@Override
public void clearPassword() {
etPassword.setText("");
}
@Override
public void toMainActivity() {
startActivity(new Intent(this, MainActivity.class));
}
@Override
public void showFailedError(Stringmessage) {
Toast.makeText(LoginActivity.this, message, Toast.LENGTH_SHORT).show();
}
@Override
public void toPassWroad() {
startActivity(new Intent(LoginActivity.this,ForgetPassActivity.class));
}
@Override
public void showLoading() {
llLoginQuan.setVisibility(View.VISIBLE);
}
@Override
public void hideLoading() {
llLoginQuan.setVisibility(View.GONE);
}
}
③model
监听网络请求
public interface GetNetListener {
//请求成功的监听
void loginSuccess(Stringrequest);
//请求失败的监听
void loginFailed(Stringerr);
}
/**
* Created by ylzx on 2016/12/21.
* 请求网络的方法
*/
public abstract class GetNet {
//登录接口
public void login(Stringusername, String password, GetNetListener loginListener){};
}
/**
* Created by ylzx on 2016/12/21.
* 请求网络
*/
public class LoginData extends GetNet {
public String TAG="LoginData";
private GetNetListener mLoginListener;
@Override
public void login(Stringusername, String password, GetNetListener loginListener) {
this.mLoginListener = loginListener;
//网络请求
try {
HashMap<String, String>sortedParams = new HashMap<String, String>();
// sysNo 值 3des加密
sortedParams.put("accountID", username);
sortedParams.put("pwd", MD5Util.md5(password));
final String url =BaseInfo.URL + "enterpriseEmployee/employeeLogin.do";
sortedParams.put("access_token", BaseInfo.ACCESS_TOKEN);//固定传参
String sign =SignUtils.sign(BaseInfo.SERVICEKEY, sortedParams);
Map<String, String>params = new HashMap<String, String>();
params.put("appid", "600000");
params.put("sign_type", "APP");
params.put("sign", sign);
for (Map.Entry<String,String> entry : sortedParams.entrySet()) {
params.put(entry.getKey(), URLEncoder.encode(DES3Util.encode(entry.getValue(),BaseInfo.SERVICEKEY)));
}
OkHttpUtils
.post()
.url(url)
.params(params)
.build()
.execute(new MyStringCallback());
} catch (Exception e) {
e.printStackTrace();
}
}
class MyStringCallback extends StringCallback {
@Override
public void onError(Call call,Exception e, int id) {
mLoginListener.loginFailed(e.toString());
}
@Override
public void onResponse(Stringresponse, int id) {
BaseModel baseModel =GsonUtil.jsonToBean(response, BaseModel.class);
if (baseModel.isFlag()){
//成功
mLoginListener.loginSuccess(response);
} else {
//错误时
mLoginListener.loginFailed(baseModel.getErrorMsg());
}
}
}
}
- 高效的使用MVP
- MVP(2)- 浅析如何高效的使用MVP
- 如何更高效的使用MVP以及官方MVP架构解析
- 如何更高效的使用MVP以及官方MVP架构解析
- 如何更高效的使用MVP以及官方MVP架构解析
- MVP的使用
- Mvp架构的使用
- MVP的简单使用
- 浅谈MVP的使用
- MVP的简单使用
- MVP的简单使用
- Android MVP架构的使用
- Android使用MVP的好处
- Android MVP 模式的使用
- MVP中RxJava的使用
- Android MVP模式的使用
- Android MVP模式的使用
- MVP模式的基本使用
- 四种读取配置信息的方式
- 刷题的日常[Leetcode]——1)Two Sum
- 支持向量机导论——没有学过机器语言也能看懂的文章
- laravel5.2中点击用户头像更改头像
- Nagios之MySQL单机与主从监控
- 高效的使用MVP
- vue---父调子 $refs (把父组件的数据传给子组件)子调父 $emit (把子组件的数据传给父组件)
- 二维数组与指针
- Java 多线程同步的五种方法
- spring计时器简单栗子
- 一个脚本引发的血案
- Python 列表
- java基础------>线程--->牛客网遇到的一题
- 开源库【FreeRadioGroup】--淡出、自由拖动、自动贴边,类似于苹果的虚拟辅助按钮