在日常的工作中,代码的解耦可能是家常便饭,有时可能谁写谁解耦,也有可能由小组中的负责人来解耦,这就要求负责人有较高的代码阅读能力了,当然这些后期劳动完全可以在前期架构搭建的时候规避掉,今天就来讲讲简单的MVP解耦。
为什么要写这个?是因为最近公司正扩招人员,通过面试一些人也了解了下刚毕业或者毕业一年左右的人的水平情况,MVC、MVP肯定是要问的,但出乎意料的是绝大多数都说一直在用MVC,MVP用得少,有的能说出MVP使用方法的也答不出如何解决MVP的内存泄漏,所以我想通过一个小文章,举一个例子就让人明白。
废话不多说直接来个图(我自己画的将就下哈):
图片.png
我们就要达到图中效果,View和Model没有联系就行,这里照顾下刚入门的新人,介绍下View是我们的界面,常把它写成一个接口,接受来自Presenter层的回调然后做出相应控件的操作,Model数据操作层,mvc中数据获取与view控件的操作都写在一起,而在mvp中什么数据库查询啊、网络获取数据啊等等都放在Model层中。Presenter层就是中间人了,他的工作就是如果View传来信息就把信息传递给model,反之同理。
简单的MVP
定义一个View接口
public interface TestLoaderMessage {
void onLoaderStart();
void onFail();
void onSuccess(String value);
}
很简单模仿下数据请求开始,然后成功与失败回调。然后就是Presenter层了,代码如下:
public class TestLoaderPresenter<V> {
private TestLoaderMessage mView;
private final TestLoaderModel mTestModel;
public TestLoaderPresenter(V view){
mView= (TestLoaderMessage) view;
mTestModel = new TestLoaderModel();
}
public void getMessageToPresenter(){
mView.onLoaderStart();
String message = mTestModel.getMessageToModel();
if(message.isEmpty()){
mView.onFail();
}else{
mView.onSuccess(message);
}
}
}
这里View层是通过构造方法传过来的,然后通过判断Model的数据返回情况调用成功或失败,接下来轮到Model层了
public class TestLoaderModel {
public String getMessageToModel(){
return "222";
}
}
这里更简单了,调这个方法就返回个字符串。模仿下服务器请求,够懒了!好,View,Presenter,Model都写了,那Activity怎么用呢?
public class Main2Activity extends AppCompatActivity implements TestLoaderMessage{
private TestLoaderPresenter mTestPresenter;
private final String TAG="Main2Activity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
}
public void mvpTest(View view){
mTestPresenter = new TestLoaderPresenter(this);
mTestPresenter.getMessageToPresenter();
}
@Override
public void onLoaderStart() {
Log.e(TAG,"onLoaderStart");
}
@Override
public void onFail() {
Log.e(TAG,"onFail");
}
@Override
public void onSuccess(String value) {
Toast.makeText(this, value, Toast.LENGTH_SHORT).show();
}
}
mvpTest方法只是个按钮点击事件,点击按钮了,初始化presenter,传入了this,所以Activity就需要实现TestLoaderMessage接口,然后presenter有了view,构造方法初始化了Model,这样view,model两个都有了,presenter就安心做它的牵线人了。
以为这样就结束了吗?NO!你看看TestLoaderPresenter初始化的时候,是不是传入了this,那么这就造成了我们最常见的内存泄漏,怎么解决它呢?当然要从presenter出手,谁引起的谁负责。定义一个基础的presenter类
public class BasePresenter<V> {
private WeakReference<V> reference;//弱引用
public void attachView(V view) {
reference = new WeakReference<V>(view);
}
public V getView() {
return reference.get();
}
public boolean isViewAttached() {
return reference != null && reference.get() != null;
}
public void disAttachView() {
if (reference != null) {
reference.clear();
reference = null;
}
}
}
然后定义基础的BaseActivity
public abstract class BaseActivity<V,T extends BasePresenter<V>> extends AppCompatActivity {
public T mPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPresenter = createPrensenter();
mPresenter.attachView((V) this);
}
@Override
protected void onDestroy() {
super.onDestroy();
mPresenter.disAttachView();
}
public abstract T createPrensenter();
}
创一个抽象的createPrensenter方法,让集成他的人都要实现这个方法,返回的是对应presenter实例,onCreate与onDestroy中进行绑定与解绑等。然后基于之前的基础改写下TestLoaderPresenter
public class TestLoaderPresenter<V> extends BasePresenter<V> {
private TestLoaderMessage mView;
private final TestLoaderModel mTestModel;
public TestLoaderPresenter(V view){
mView= (TestLoaderMessage) view;
mTestModel = new TestLoaderModel();
}
public void getMessageToPresenter(){
mView.onLoaderStart();
String message = mTestModel.getMessageToModel();
if(message.isEmpty()){
mView.onFail();
}else{
mView.onSuccess(message);
}
}
}
就对了个集成没其他的。绑定解绑都在BasePresenter里面完成,那么Activity中也得集成我们的BaseActivity了,当然不要忘记createPrensenter方法的实现。
public class Main2Activity extends BaseActivity<TestLoaderMessage,TestLoaderPresenter<TestLoaderMessage>> implements TestLoaderMessage{
private TestLoaderPresenter mTestPresenter;
private final String TAG="Main2Activity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
}
@Override
public TestLoaderPresenter<TestLoaderMessage> createPrensenter() {
return new TestLoaderPresenter<TestLoaderMessage>(this);
}
public void mvpTest(View view){
mTestPresenter = new TestLoaderPresenter(this);
mTestPresenter.getMessageToPresenter();
}
@Override
public void onLoaderStart() {
Log.e(TAG,"onLoaderStart");
}
@Override
public void onFail() {
Log.e(TAG,"onFail");
}
@Override
public void onSuccess(String value) {
Toast.makeText(this, value, Toast.LENGTH_SHORT).show();
}
}
我们最基础的MVP架构就完成了。
网友评论