Android之MVP(二)之深入封装
来源:互联网 发布:linux 添加组 编辑:程序博客网 时间:2024/06/05 19:43
http://blog.csdn.net/dantestones/article/details/51445208
Android之mvp(一)之入门使用中我简单的介绍了mvp,以及怎么写mvp。我自己也将mvp运用到了项目中,其实mvp并没有固定的写法,正确的去理解架构的思想,都可以有自己独特的mvp写法。git上也有很多例子,比如google的android-architecture,simple哥的Android 源码设计模式解析与实战中也有mvp的讨论。这里参考了simple哥做了一个通用版的mvp,并对google的MVP做了一点自己的解析。
关于presenter一直持有Activity对象导致的内存泄漏问题
只要用过mvp这个问题可能很多人都知道。写mvp的时候,presenter会持有view,如果presenter有后台异步的长时间的动作,比如网络请求,这时如果返回退出了Activity,后台异步的动作不会立即停止,这里就会有内存泄漏的隐患,所以会在presenter中加入一个销毁view的方法。现在就在之前的项目中做一下修改
//presenter中添加mvpView 置为null的方法public void onDestroy(){ mvpView = null;}//退出时销毁持有Activity@Overrideprotected void onDestroy() { mvpPresenter.onDestroy(); super.onDestroy();}
presenter中增加了类似的生命周期的方法,用来在退出Activity的时候取消持有Activity。
但是在销毁后需要思考一点,后台的延时操作返回时,这个时候view被销毁了,如果接着去调用view的方法就 会抛出空指针异常。所以在后台的延时操作中需要考虑到这种可能产生空指针的情况,尤其是网络请求。
BasePresenter
如果每一个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我就可以把原来的MvpPresenter简化成下面的样子
public class LoginPersenter extends BasePresenter<IUserLoginView> { IUserLoginView loginView; LoginModel loginModel; private Handler mHandler = new Handler(); public LoginPersenter(IUserLoginView loginView) { this.loginView = loginView; loginModel = new LoginModel(); } public void clear() { loginView.clearPassword(); loginView.clearUserName(); } public void login() { loginView.showLoading(); loginModel.login(loginView.getUsername(), loginView.getPassword(), new OnLoginListener() { @Override public void loginSuccess(final User user) { mHandler.post( new Runnable() { @Override public void run() { loginView.hideLoading(); loginView.UpdateView(user); } } ); } @Override public void loginFailed() { mHandler.post( new Runnable() { @Override public void run() { loginView.hideLoading(); loginView.showFailedError(); } } ); } }); }}
BaseView
界面需要提供的UI方法中会有很多类似的UI方法,可以把它们提取到一个公共的父类接口中。比如提取显示loading界面和隐藏loading界面的方法,其他的view层接口就可以直接继承BaseView接口,不必重复的写显示和隐藏loading界面方法。
public interface BaseView { void showLoading(); void hideLoading();}
BaseMvpActivity
presenter绑定到activity和View的绑定和解绑操作是每个Activity都会去做的,同样这里我也希望能有一个父类来完成这个统一的操作。
public abstract class BaseMvpActivity <V,T extends BasePresenter<V>> extends AppCompatActivity { public T presenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); presenter = initPresenter(); } @Override protected void onResume() { super.onResume(); presenter.attach((V)this); } @Override protected void onDestroy() { presenter.dettach(); super.onDestroy(); } // 实例化presenter public abstract T initPresenter();}
同样使用泛型来提取通用的逻辑,presenter的初始化,以及view的绑定和解绑操作都提取到父类Activity中。向外部提供了一个 initPresenter();
方法用来初始化presenter,如果想创建不同参数的构造函数都可以随意去创建。
更加通用的例子
通过上面的base父类,对之前的例子进行优化,写一个更加好用的例子。
- IUserLoginView继承BaseView接口,添加自己的初始化方法
public interface IUserLoginView extends BaseView{ void clearUserName(); void clearPassword(); String getUsername(); String getPassword(); void UpdateView(User user); void showFailedError();}
- LoginPresenter 继承BasePresenter类,增加网络请求和处理点击事件的方法
public class LoginPersenter extends BasePresenter<IUserLoginView> { IUserLoginView loginView; LoginModel loginModel; private Handler mHandler = new Handler(); public LoginPersenter(IUserLoginView loginView) { this.loginView = loginView; loginModel = new LoginModel(); } public void clear() { loginView.clearPassword(); loginView.clearUserName(); } public void login() { loginView.showLoading(); loginModel.login(loginView.getUsername(), loginView.getPassword(), new OnLoginListener() { @Override public void loginSuccess(final User user) { mHandler.post( new Runnable() { @Override public void run() { loginView.hideLoading(); loginView.UpdateView(user); } } ); } @Override public void loginFailed() { mHandler.post( new Runnable() { @Override public void run() { loginView.hideLoading(); loginView.showFailedError(); } } ); } }); }}
- MainActivity
public class MainActivity extends BaseMvpActivity<IUserLoginView, LoginPersenter> implements IUserLoginView { private EditText mEtUsername, mEtPassword; private Button mBtnLogin, mBtnClear; private ProgressBar mPbLoading; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_user_login); initViews(); } private void initViews() { mEtUsername = (EditText) findViewById(R.id.id_et_username); mEtPassword = (EditText) findViewById(R.id.id_et_password); mBtnClear = (Button) findViewById(R.id.id_btn_clear); mBtnLogin = (Button) findViewById(R.id.id_btn_login); mPbLoading = (ProgressBar) findViewById(R.id.id_pb_loading); mBtnLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { presenter.login(); } }); mBtnClear.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { presenter.clear(); } }); } @Override public void showLoading() { mPbLoading.setVisibility(View.VISIBLE); } @Override public void hideLoading() { mPbLoading.setVisibility(View.GONE); } @Override public String getUsername() { return mEtUsername.getText().toString(); } @Override public String getPassword() { return mEtPassword.getText().toString(); } @Override public void UpdateView(User user) { Toast.makeText(this, "登录成功!!!", Toast.LENGTH_SHORT).show(); } @Override public void clearUserName() { mEtUsername.setText(""); } @Override public void clearPassword() { mEtPassword.setText(""); } @Override public void showFailedError() { Toast.makeText(this, "登录失败!!!", Toast.LENGTH_SHORT).show(); } @Override public LoginPersenter initPresenter() { return new LoginPersenter(this); }}最终的成果,我们只需要在Acitivity中传入泛型对象,并写好
initPresenter()
Presenter的初始化的方法就可以直接去使用presenter,当然View的接口还是要自己去实现。 以上的方法只是一些比较简单的封装。
- Android之MVP(二)深入封装
- Android之MVP(二)之深入封装
- Android之mvp设计模式(二)
- Android高仿微信之mvp实现(二)
- Android 当中的 MVP 模式(二)封装
- Android之MVP模式
- Android架构之MVP
- Android 之MVP思想
- Android架构之MVP
- Android之MVP架构
- android探索之MVP
- android之MVP
- Android 之MVP模式
- android 之MVP模板
- Android之Adapter的封装与抽象(二)
- Android控件封装之跑马灯(二)
- Android 设计模式之二:MVP模式与MVC模式 .
- Android之MVP入门使用(一)
- UVA 644-Immediate Decodability
- event.keyCode用法及列表
- E A S Y 实现文件上传下载【更新版本】
- 纯CSS视差滚动
- UVA327Evaluating Simple C Expressions
- Android之MVP(二)之深入封装
- 【HDU 1175】连连看(DFS)
- Remove Linked List Elements
- 如何在ubuntu下安装vmware-tools
- Java进阶(三十五)java int与integer的区别
- 基于Oracle数据库的检索优化研究与分析
- Android收集应用崩溃信息
- Python——5函数
- hdu 5726 GCD(2016 Multi-University Training Contest 1线段树)