前言

最近在封装MVP模式时,由于Presenter与View的base接口用了泛型进行限制,将View与Presenter关联起来时导致编译无法通过。因此唠叨一番

场景

直接上base的view和presenter,同时看看大家能解决关联的问题吗

1
2
3
#View
public interface IMvpView{
}
1
2
3
4
5
6
7
8
9
10
11
#Presenter
public interface IMvpPresenter<V extends IMvpView> {
/**
* 初始化Presenter时,用于presenter与view绑定
*/
void onBind(V view);

void onViewAttach();

void onViewDetach();
}

现在要写一个帮助方法来讲View和Presenter结合起来,即调用onBind方法

最简单的莫过于,直接调用

1
2
3
public void LoginView(){
new LoginPresenter().onBind(this);
}

但是那岂不是所有的view里面创建presenter后接着调用onBind方法,因此写了下面的方法

1
2
3
4
5
#帮助类里
public static <V extends IMvpView, P extends IMvpPresenter<V>> P from(V view, P presenter) {
presenter.onBind(view);
return presenter;
}

看方法貌似没有啥问题,但是当你使用的是会报错的。要求presenter的泛型必须是LoginView类。
看一下我们写的确实是有问题,V当成泛型直接给了IMvpPresenter。那我们要怎么写才能避免这种报错呢
我采用大多数问题都可以通过引入第三方的方式来解决(类、变量等)的原则,所以写出了下面的方法

1
2
3
4
public static <T extends IMvpView, P extends IMvpPresenter<T>, V extends T> P from(V view, P presenter) { //需要使用T作为中介
presenter.onBind(view);
return presenter;
}

问题解决,但是下面介绍一种其他方法,使用通配符

泛型的一些知识

这里我有一些总结,可以大体看一下。泛型
其中通配符用?表示,由于他的类型表示一组未知的类型,所以我们即使写成IMvpPresenter<?>也不会报错。
我们利用这一点,写出下面的方法

1
2
3
4
public static <V extends IMvpView, P extends IMvpPresenter<? super V>> P from(V view, P presenter) {
presenter.onBind(view);
return presenter;
}

通配符虽然可以绕过声明的报错,但是使用时还是要遵循泛型的边界的,所以这里用到了super V。同时限制V的类型

本文只是记录日常开发遇到的小问题,没有深入研究,对此感到抱歉,后期会对泛型进行详细研究