Github地址:android-presenter
MVP优点:view由Activity承担,Presenter做业务,结构清晰(模式么就是讲究一个套路,结构清晰后来者维护也是受益的)。之前开发都是全写一个类-Activity里面,业务复杂的情况下看着头疼。理想化Presenter层应该是不包含android代码,使junit,我是没使用。
通过注解绑定Presenter:一般情况下每个view有个presenter ,代码量也就多了。那如何将Presenter重用起来呢?答案就是通过注解了。
看代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface BindP {
@SuppressWarnings("rawtypes")
Class<? extends Presenter>[] value();
}
我们再来看看Presenter
public abstract class Presenter<V> {
//view
private V view;
//isAttached
private boolean isAttached = false;
/**
* getViewInstance
*
* @return view
*/
protected final V getViewInstance() {
return view;
}
/**
* isAttached
*
* @return isAttached
*/
public final boolean isAttached() {
return isAttached;
}
/**
* attach
*
* @param view view
*/
public void onAttach(V view) {
this.view = view;
isAttached = true;
}
/**
* dettach
*/
public void onDettach() {
isAttached = false;
view = null;
}
/**
* response
*
* @param data data
* @param <D> data type
* @return callback
*/
protected <D> Response1<D> response(D data) {
return new Response1<D>(data);
}
/**
* response
*
* @return callback
*/
protected Response response() {
return new Response();
}
/**
* Response
*/
protected class Response {
/**
* back
*
* @param action back
*/
public Response back(OnAction action) {
if (isAttached() && action != null && getViewInstance() != null) {
action.action(getViewInstance());
}
return this;
}
}
/**
* Response1
*
* @param <D> data type
*/
protected class Response1<D> {
private D data;
public Response1(D data) {
this.data = data;
}
public <C> Response1<C> map(OnMap<D, C> map) {
return new Response1<C>(map.map(data));
}
/**
* back
*
* @param callback callback
*/
public Response1<D> back(OnCallback<D> callback) {
if (isAttached() && callback != null && getViewInstance() != null) {
callback.callback(getViewInstance(), data);
}
return this;
}
}
/**
* OnAction
*/
protected abstract class OnAction {
public abstract void action(V view);
}
/**
* OnMap
*
* @param <D> data type
* @param <C> to type
*/
protected abstract class OnMap<D, C> {
public abstract C map(D data);
}
/**
* OnCallback
*
* @param <D> data type
*/
protected abstract class OnCallback<D> {
public abstract void callback(V view, D data);
}
}
从代码我们可以看出,Presenter的生命周期函数只有两个onAttach()
和onDettach()
分别表示与View的绑定与解除绑定事件。
将Presenter绑定到View中
public class PresenterBind {
private PresenterBind() {
}
/**
* bindPresenter
*
* @param object object
* @return presenter holder
*/
@SuppressWarnings("rawtypes")
public static PresenterHolder bind(Object object) {
PresenterHolder handler = new PresenterHolder();
if (object == null)
return handler;
Class<?> clazz = object.getClass();
for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
BindP presenter = clazz.getAnnotation(BindP.class);
if (presenter != null) {
Class<? extends Presenter>[] presenterTypes = presenter.value();
for (Class<? extends Presenter> presenterType : presenterTypes) {
if (verifyPresenter(presenterType, object.getClass())) {
try {
Presenter pre = presenterType.getConstructor().newInstance();
handler.addPresenter(pre);
} catch (Exception e) {
}
}
}
}
}
handler.onAttach(object);
return handler;
}
/**
* addPresenter
*
* @param handler holder
* @param presenters presenters
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public static void bind(PresenterHolder handler, Class<? extends Presenter>... presenters) {
if (handler == null || handler.getTarget() == null || presenters == null)
return;
for (Class<? extends Presenter> presenterType : presenters) {
if (verifyPresenter(presenterType, handler.getTarget().getClass())) {
if (!handler.hasPresenter(presenterType)) {
try {
Presenter pre = presenterType.getConstructor().newInstance();
handler.addPresenter(pre);
pre.onAttach(handler.getPersenters());
} catch (Exception e) {
}
}
}
}
}
/**
* verifyPresenter
*
* @param presenter presenter
* @param viewClass viewClass
* @return false or true
*/
@SuppressWarnings("rawtypes")
private static boolean verifyPresenter(Class<? extends Presenter> presenter, Class<?> viewClass) {
Class<?> viewPresenterClass = getViewClass(presenter);
if (isClassGeneric(viewClass, viewPresenterClass.getName()))
return true;
return false;
}
/**
* getViewClass
*
* @param presenter presenter
* @return view class
*/
@SuppressWarnings("rawtypes")
private static Class<?> getViewClass(Class<? extends Presenter> presenter) {
if (presenter != null) {
Class<?> entityClass = null;
Type t = presenter.getGenericSuperclass();
if (t instanceof ParameterizedType) {
Type[] p = ((ParameterizedType) t).getActualTypeArguments();
entityClass = (Class<?>) p[0];
}
return entityClass;
}
return null;
}
/**
* isGeneric
*
* @param clazz clazz
* @param name name
* @return true or false
*/
private static boolean isClassGeneric(Class<?> clazz, String name) {
for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
if (name.equals(clazz.getName())) {
return true;
}
Class<?>[] classes = clazz.getInterfaces();
for (int i = 0; i < classes.length; i++) {
if (name.equals(classes[i].getName())) {
return true;
}
}
}
return false;
}
}
我们通过PresenterBind.bind(Object object) 解析并实例化Presenter,返回PresenterHolder 作为Presenter的持有者。
public class PresenterHolder {
@SuppressWarnings("rawtypes")
private Map<String, Presenter> persenterMap = new HashMap<String, Presenter>();
// is attached
private boolean isAttached = false;
//target
private Object target = null;
/**
* getTarget
*
* @return target
*/
public Object getTarget() {
return target;
}
/**
* putPresenter
*
* @param presenter presenter
*/
@SuppressWarnings("rawtypes")
protected void addPresenter(Presenter presenter) {
if (presenter == null) {
return;
}
if (hasPresenter(presenter.getClass())) {
return;
}
persenterMap.put(presenter.getClass().getName(), presenter);
}
/**
* onAttach
*
* @param object object
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public void onAttach(Object object) {
if (isAttached) {
return;
}
if (!isEmpty()) {
for (Map.Entry<String, Presenter> entry : persenterMap.entrySet()) {
entry.getValue().onAttach(object);
}
}
target = object;
isAttached = true;
}
/**
* isAttached
*
* @return is attached
*/
public boolean isAttached() {
return isAttached;
}
/**
* onDettach
*/
@SuppressWarnings("rawtypes")
public void onDettach() {
if (isAttached) {
for (Map.Entry<String, Presenter> entry : persenterMap.entrySet()) {
entry.getValue().onDettach();
}
persenterMap.clear();
isAttached = false;
}
}
/**
* isEmpty
*
* @return is empty
*/
public boolean isEmpty() {
return persenterMap.isEmpty();
}
/**
* getPersenters
*
* @return persenterMap
*/
@SuppressWarnings("rawtypes")
public Map<String, Presenter> getPersenters() {
return persenterMap;
}
@SuppressWarnings("rawtypes")
public boolean hasPresenter(Class<? extends Presenter> cls) {
if (persenterMap.containsKey(cls.getName())) {
return true;
}
return false;
}
/**
* getPresenter
*
* @param clazz clazz
* @param <T> t
* @return presenter
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public <T extends Presenter> T getPresenter(Class<T> clazz) {
if (hasPresenter(clazz)) {
return (T) persenterMap.get(clazz.getName());
}
return null;
}
}
具体使用
创建Presenter
public class BasePresenter extends Presenter<BasePresenter.IView> {
public static interface IView {
void toast(String s);
}
public void showToast() {
response("show toast").back(new OnCallback<String>() {
@Override
public void callback(IView view, String data) {
view.toast(data);
}
});
}
}
使用Presenter
@BindP(BasePresenter.class)
public class MainActivity extends AppCompatActivity implements BasePresenter.IView {
private PresenterHolder holder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
holder = PresenterBind.bind(this);
holder.getPresenter(BasePresenter.class).exec();
}
@Override
public void toast(String s) {
Toast.makeText(this, s, Toast.LENGTH_SHORT).show();
}
@Override
protected void onDestroy() {
super.onDestroy();
holder.onDettach();
}
}