在Mvp架構中Activity需要創建Presenter對象,並處理與Presenter的綁定、解除綁定關係,這是View層公共的邏輯,可以把這些邏輯抽取到Base中統一處理,然而一個Activity中可能需要創建多個Presenter對象,這就需要在Activity中創建一個List列表來存儲這個頁面中所有的Presenter對象,在具體的子類Activiy中並不確定到底有多少個Presenter對象,解決這個問題可以爲子類提供一個抽象方法,通過實現這個抽象方法子類Activity將所有創建的Presenter對象手動添加進去,這樣操作起來會有點麻煩,而且在實際編碼過程中還經常會忘記這步操作。這裏通過自定義註解的方式來解決這個問題,具體就是通過爲Presenter變量添加註解,在基類中解析註解信息自動創建Presenter對象、自動維護List列表和相關邏輯,做到子類完全不用關心這些操作,下面看下代碼實現:
1、創建自定義註解類
package com.znh.commonlib.base.inject;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by znh on 2019/6/3
*/
@Target(ElementType.FIELD) //註釋1
@Retention(RetentionPolicy.RUNTIME) //註釋2
public @interface InjectPresenter {
}
上述代碼就定義了一個註解InjectPresenter,註釋1代表該註解作用於成員變量,註釋2代表該註解是運行時註解。
2、創建基類BaseMvpActivity處理相關邏輯
package com.znh.commonlib.base;
import android.os.Bundle;
import android.support.annotation.Nullable;
import com.znh.commonlib.base.inject.InjectPresenter;
import com.trello.rxlifecycle2.components.support.RxAppCompatActivity;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
/**
* Created by znh on 2019/6/3
* <p>
* MvpActivity基類
*/
public abstract class BaseMvpActivity extends RxAppCompatActivity implements IBaseView {
//存儲當前頁面中對應的所有的Presenter
public List<BasePresenter> mPresenters;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutId());
//處理Presenter的創建和綁定
mPresenters = new ArrayList<>();
createAndBindPresenter();
initView();
initData();
}
/**
* 獲取頁面佈局id
*
* @return
*/
public abstract int getLayoutId();
/**
* 初始化View
*/
protected abstract void initView();
/**
* 初始化數據
*/
protected abstract void initData();
/**
* 創建並綁定Presenter
*/
public void createAndBindPresenter() {
//通過反射注入Presenter
Field[] fields = this.getClass().getDeclaredFields();
for (Field field : fields) {
InjectPresenter injectPresenter = field.getAnnotation(InjectPresenter.class);
if (injectPresenter != null) {
//註釋3
if (!BasePresenter.class.isAssignableFrom(field.getType())) {
throw new RuntimeException("InjectPresenter annotations have incorrect field types and can only be used for BasePresenter and its subclasses");
}
Class<? extends BasePresenter> basePresenterClazz = (Class<? extends BasePresenter>) field.getType();
try {
//註釋4 創建對象
BasePresenter basePresenter = basePresenterClazz.newInstance();
basePresenter.attachView(this);
//設置字段
field.setAccessible(true);
field.set(this, basePresenter);
//註釋5 添加Presenter
mPresenters.add(basePresenter);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* 解綁Presenter
*/
public void unBindPresenter() {
for (BasePresenter basePresenter : mPresenters) {
basePresenter.detachView();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unBindPresenter();
}
}
在onCreate方法中創建mPresenters列表用來存儲頁面中所有的Presenter對象,然後調用createAndBindPresenter方法創建頁面中所有的Presenter對象,並處理綁定邏輯,在註釋3處校驗註解作用的字段是否是BasePresenter類型的,如果不是就拋出異常,註釋4處通過反射創建出Presenter實例對象並和View進行綁定,註釋5處將創建的Presenter實例對象添加到集合列表中進行管理。在Activity的onDestroy方法中調用unBindPresenter方法對所有跟這個Activity有綁定關係的Presenter進行解除綁定,防止內存泄漏。
3、在代碼中直接使用註解
package com.znh.commonlib.base;
import com.znh.commonlib.base.inject.InjectPresenter;
/**
* Created by znh on 2019/6/3
* <p>
* 測試頁面
*/
public class TestActivity extends BaseMvpActivity {
@InjectPresenter
private Presenter1 mPresenter1;
@InjectPresenter
private Presenter2 mPresenter2;
@InjectPresenter
private Presenter3 mPresenter3;
public void loadData() {
mPresenter1.loadData();
mPresenter2.loadData();
mPresenter3.loadData();
}
...........
}
在Activity子類中如果需要使用哪個Presenter,就直接將對應的Presenter聲明爲成員變量併爲其添加@InjectPresenter註解,就可以直接在代碼中調用對應Presenter的方法,不需要關心其他的操作。