我有BaseFragment
:
public abstract class BaseFragment extends Fragment implements BaseMvpView {
private BasePresenter presenter;
protected void syncLifeCycle(BasePresenter presenter) {
this.presenter = presenter;
this.presenter.onCreate();
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//noinspection unchecked
presenter.onAttachView(this); //it works with a warning
}
@Override
public void onResume() {
super.onResume();
presenter.onResume();
}
@Override
public void onPause() {
super.onPause();
presenter.onPause();
}
@Override
public void onDestroyView() {
super.onDestroyView();
presenter.onDetachView();
}
@Override
public void onDestroy() {
super.onDestroy();
presenter.onDestroy();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
presenter.onActivityResult(requestCode, resultCode, data);
}
}
和许多扩展它的类。例如MainFragment
:
public class MainFragment extends BaseFragment implements MainMvpView {
MainPresenter<MainMvpView> presenter;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
syncLifeCycle(presenter);
//presenter.onCreate();
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//presenter.onAttachView(this);
}
@Override
public void onResume() {
super.onResume();
//presenter.onResume();
}
@Override
public void onPause() {
super.onPause();
//presenter.onPause();
}
@Override
public void onDestroyView() {
super.onDestroyView();
//presenter.onDetachView();
}
@Override
public void onDestroy() {
super.onDestroy();
//presenter.onDestroy();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//presenter.onActivityResult(requestCode, resultCode, data);
}
}
我想避免重复每个片段和演示者的生命周期同步代码。因此,我想在BaseFragment
中实现此过程。在Java中,这一行presenter.onAttachView(this);
有效但警告“未经检查的呼叫onAttachView(V)
”(我可以忍受这一点)。但 Kotlin 不允许我这样做
abstract class BaseFragmentKotlin : Fragment(), BaseMvpView {
private var presenter: BasePresenter<*>? = null
//...
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
presenter?.onAttachView(this) //Does not work. "Out-projected type 'BasePresenter<*>?' prohibits the use of 'public abstract fun onAttachView(mvpView: V!): Unit defined in com.example.test.BasePresenter"
}
//...
}
我真的需要有关如何正确执行此操作的建议。
编辑:
public class BasePresenterImpl<V extends BaseMvpView> implements BasePresenter<V> {
@Nullable
public V mvpView;
@Override
public void onCreate() {
}
@Override
public void onAttachView(V mvpView) {
this.mvpView = mvpView;
}
@Override
public void onResume() {
}
@Override
public void onPause() {
}
@Override
public void onDetachView() {
mvpView = null;
}
@Override
public void onDestroy() {
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
}
}
以下是整个测试代码https://github.com/AlexNikolaTest/Test/tree/master/app/src/main/java/com/example/mytest
答案 0 :(得分:5)
我认为将star-projection替换为BaseMvpView
会有所帮助
abstract class BaseFragmentKotlin : Fragment(), BaseMvpView {
private var presenter: BasePresenter<BaseMvpView>? = null
//...
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
presenter?.onAttachView(this)
}
//...
}
原因是Kotlin区分out
和in
类型参数(也分别称为协变和逆变参数类型)。
in
类型参数声明类型参数将被泛型类消耗,即用作函数的参数,而out
类型参数声明泛型类将生成传递类型的值
参数,即用作某些函数的返回类型。
onAttachView(V mvpView)
采用逆变型参数,这意味着V
不允许任何类型(它必须是BaseMvpView
类型或子类),因为你消费该值。也就是说,如果V
完全未知,我们无法安全地读取参数,因为V
应该是BaseMvpView
的实例。但是,如果是onAttachView
生成的情况,即。返回,V
对象然后星形投影将起作用。
希望这有帮助!
答案 1 :(得分:3)
也许你可以这样做
interface IView
interface IPresenter {
fun attachView(v: IView)
fun detachView()
}
abstract class BasePresenter<V :IView> : IPresenter {
protected var view: V? = null
override fun attachView(v: IView) {
this.view = v as V
}
override fun detachView() {
view = null
}
}
abstract class BaseFragment<P : IPresenter> : Fragment(), IView {
protected lateinit var presenter: P
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
presenter.attachView(this)
}
override fun onDestroyView() {
super.onDestroyView()
presenter.detachView()
}
}
interface TestView : IView {
fun doSomething()
}
interface TestPresenter : IPresenter {
fun doSomething()
}
class TestPresenterImpl : BasePresenter<TestView>(), TestPresenter {
override fun doSomething() {
}
}
class TestFragment : BaseFragment<TestPresenter>(), TestView {
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
presenter = TestPresenterImpl()
presenter.doSomething()
}
override fun doSomething() {
}
}
答案 2 :(得分:3)
你可以尝试这个,然后你也可以在Kotlin中获得未经检查的警告; - )
if (presenter != null) {
val p = presenter as BasePresenter<BaseMvpView>
p.onAttachView(this)
}
在您的MainFragment中
syncLifeCycle(presenter as BasePresenter<BaseMvpView>)
不确定它是否有效,只是在IntelliJ中玩了一下。但是由于在编译期间擦除了泛型并且将MainPresenter转换为BasePresenter也应该没问题,因此它很有可能会通过。